最初のコード:
_List<Integer>[] array = (List<Integer>[]) new Object[size];
_
次の例外が発生します。
Java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.util.List; ([Ljava.lang.Object; and [Ljava.util.List; are in module Java.base of loader 'bootstrap')
なぜこれが間違っているのですか? Effective Java Third EditionPage 132の方法に従います:
2番目のコード:
_E[] array = (E[]) new Object[size];
_
しかし、私は次のコードが機能することを発見しました
番目のコード:
_List<Integer>[] array = (List<Integer>[]) new List[size];
_
私の質問:
たとえば、次のコードはうまく機能するが、最初のコードが間違っているのはなぜですか。
_public class Test<E>{
E[] array;
public Test(){
array = (E[]) new Object[10];
}
public E set(E x){
array[0] = x;
System.out.println(array[0]);
return array[0];
}
public static void main(String[] args){
Test<List<Integer>> test = new Test<>();
List<Integer> list = new ArrayList<>();
list.add(1);
test.set(list);
}
}
_
4番目のコード:
_List<Integer>[] array = new List<Integer>[size];
_
Javaでの配列とジェネリックス間の相互作用は、それらが異なる仮定に基づいて構築されているため、面倒です。Java配列にはランタイムタイプチェックがあり、ジェネリックスにはコンパイル時タイプしかありません。チェックしています。
Javaは、コンパイル時チェックと実行時チェックを組み合わせることにより、タイプセーフを実装します。キャストはほとんどのコンパイル時チェックをバイパスしますが、実行時チェックはまだ残っています。配列は、それらが含む要素型と基本的に同じ型互換性ルールを持っています。そう:
_Object[] a = new String[size]; //ok, but be aware of the potential for an ArrayStoreException
String[] a = new Object[size]; //compile error
String[] a = (String[]) new Object[size]; //runtime error
_
サンがJavaにジェネリックを追加することを決定したとき、ジェネリックを使用するコードは既存のJVMで動作するはずであると決定しました。時間はプレーンタイプに置き換えられます。
したがって、消去する前に次のステートメントがあります。
_List<Integer>[] array = (List<Integer>[]) new Object[size];
E[] array = (E[]) new Object[size];
List<Integer>[] array = (List<Integer>[]) new List[size];
_
消去後。
_List[] array = (List[]) new Object[size]; //run time error.
Object[] array = (Object[]) new Object[size]; //no error.
List[] array = (List[]) new List[size]; //no error.
_
E[] array = (E[]) new Object[size];
構造体は注意して使用する必要があります。これは、Java)の通常の型指定モデルの違反であり、配列が非に返されると、混乱を招くClassCastExceptionを引き起こしますジェネリックコンテキスト。残念ながら、型を消去するため、ジェネリック型が要素型を見つけて正しい型の配列を構築する方法がないため、これ以上の選択肢はありません。