4

まずジェネリックの新製品。ここで質問 - HashMap.java には次のように表示されます -

 transient Entry[] table; 
 which is initiated in constructor as
 table = new Entry[capacity];

これが型パラメーターで宣言されなかったのはなぜですか?

または

 private V getForNullKey() {
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {

for ループのエントリが型パラメータで宣言されたのはなぜですか?

深いコンセプトがあるのか​​、それとも手頃な価格の矛盾があるだけなのか?

4

1 に答える 1

7

これは、具体的なパラメーター化された型の配列を作成することはタイプ セーフではないためであり、それがまったく許可されていない理由です。

次のようなコードを作成しようとすると、コンパイラ エラーが発生します。

List<String>[] arr = new ArrayList<String>[10]; // Compiler error: Generic Array creation

問題は、ジェネリック型が具体化できないことです。それらの型情報は実行時に利用できません。一方、配列は、実行時に利用可能な型情報を使用しArrayStoreCheckて、配列に挿入された要素が配列の型と互換性があるかどうかを確認します。したがって、配列とジェネリックを混同すると、実行時に驚くべき動作が発生する可能性があります。

たとえば、次のコードを考えてみましょう。

List<String>[] arr = new ArrayList<String>[10];  // Suppose this was valid
Object[] objArr = arr;         // This is valid assignment. A `List[]` is an `Object[]`
objArr[0] = new ArrayList<Integer>();  // There you go. A disaster waiting at runtime.

String str = arr[0].get(0);    // Assigned an `Integer` to a `String`. ClassCastException

そのため、最初の代入がコンパイルされていれば、コンパイラには問題ないように見える 4 番目の代入がClassCastException実行時にスローされます。


ただし、どちらも完全に具体化可能な型であるため、生の型の配列 - ArrayList、または無制限のワイルドカード パラメータ化された型 -を作成できます。ArrayList<?>したがって、次の配列の作成は有効です。

List[] arr = new ArrayList[10];
List<?>[] arr2 = new ArrayList<?>[10];

生の型または無制限のワイルドカード型に関連付けられた型情報がないため、実行時に失うものは何もありません。したがって、これらの型は具体化可能であり、配列の適切なコンポーネント型です。そのため、Entry[]の代わりに が使用されEntry<K, V>[]ます。


以下も参照してください。

于 2013-10-13T22:22:40.497 に答える