Javaジェネリック型キャストが必要ですか?

Java Generics Type Casting Necessary?


質問 written by Myang310 @2016-04-01 22:40:11Z

: 6 : 3 : 176

これは私の教科書のコードです:

Stack<String>[] a = (Stack<String>[]) new Stack[N];

私の質問は:

  1. なぜ「新しいStack [N]」なのですか?
  2. 作成した新しいスタック配列で型変換を行う必要があるのはなぜですか? 私はちょうどそれを試しました

     Stack<String>[] a = new Stack[N]; 

コンパイルして正常に実行されました。 文字列をにプッシュしてpopメソッドを印刷した後でも。 また、intをプッシュするとすぐにコンパイラエラーが発生するので、なぜ型キャストする必要があるのですか

Stack<String>[] 

具体的には?

コメント 1

Java 8を使用していますか?ジェネリックシステムを使用することで改善された点がいくつかあります。

written by 誠 @2016-04-01 22:48:08Z

回答 1 written by zer0chain @2016-04-01 23:06:00Z
4

パラメーター化された型の配列を作成することはできません( ジェネリックの制限を参照)。 したがって、 ... = new Stack<String>[N]使用することはできません。 ... = new Stack[N]すると動作しますが、未チェックの変換に対して警告が表示されます(警告を表示するにはjavacで-Xlintを使用します)。

したがって、唯一の適切な方法は、生のパラメーターを使用して配列を作成し、必要な型にチェックキャストを適用することです。

コメント 1

そうですか!どうもありがとう。リンクを読みましたが、繰り返しになるかもしれませんが、今ではもっと意味があります。

written by Myang310 @2016-04-01 23:15:17Z

コメント 2

それでは、チェックされたキャストを含めないことの害は何ですか?

written by Myang310 @2016-04-01 23:16:26Z

コメント 3

本当に害はありません。互換性の理由で、以前のジェネリック前バージョンのJavaとの未チェックの変換が存在します。警告は、汎用性を使用する必要があることをdevに思い出させます。未チェックの変換を参照してください。

written by -zer0chain @2016-04-01 23:26:52Z

コメント 4

..または、このような配列の場合:代わりにリストの使用を検討してください。[ArrayList]実装自体は、質問のコードと同様のコードを処理しますが、詳細、wrt配列、およびジェネリックが漏れることを防ぎます。

written by -user2864740 @2016-04-01 23:27:26Z

回答 2 written by gustf @2016-04-01 23:14:14Z
1
  1. その質問の意味がわかりませんが、なぜ新しいStack<String>[N] を使用しないのかというのは、Java 配列がパラメーター化された配列の作成をサポートしていないためです。

  2. (1)での私の答えのため、作成された配列はパラメーター化されていませんが、パラメーター化された変数に割り当てています。 そのため、オプションですが、優先キャストが推奨されます。

コメント 1

ええ、わかりました。それが用語です(パラメータ化されていません)。では、パラメーター化された変数を割り当てずにStack [N]のままにしておくと、どのような危険がありますか?

written by Myang310 @2016-04-01 23:17:18Z

コメント 2

@ zer0chainが言及したように、実際には危険はなく、単なる警告です。 未チェックの変換

written by -gustf @2016-04-01 23:35:39Z

回答 3 written by newacct @2016-04-15 00:13:24Z
0

まず、気づいたように、キャストは不要です。 キャストがないと、未チェックの変換警告が表示されます(キャストでは、未チェックのキャスト警告が表示されます)。 生の型とパラメータ化された型の間の変換は、明示的なキャストなしで行うことができます(警告が表示されるだけです)。

パラメーター化された型の配列を直接作成できない理由について質問している場合、これは、Javaの配列が実行時に、配列がコンポーネント型のインスタンスではない要素を保持しないことを保証するためですで作成されました。 すなわち、ランタイムチェックは、何かが配列に入れられるたびに実行され、それが配列のコンポーネントタイプのインスタンスであるかどうかをチェックします。

ご存知かもしれませんが、ジェネリック型の引数はコンパイル時には存在せず、実行時にパラメーター化された型のinstanceofをチェックすることはできません。 instanceof化された型のチェックのみが可能です。 パラメータ化された型で配列を作成できる場合、実行時に配列に入れられたすべてがその型のインスタンスであることを確認するという契約を履行することはできません。 この配列の保証に依存している人は、予期しない結果を得るでしょう。 したがって、それを行うことはできません。 ただし、未加工の型(実行したもの)、またはワイルドカードパラメーター化された型を使用して配列を作成することは、これらが具体化型であるため問題ありません。 これをパラメーター化された型の配列として使用していますが、チェックなしの変換(警告付き)を通じてそれを行ったため、発生する可能性のある安全性の問題に責任を負います。