import java.lang.reflect.Array;
public class PrimitiveArrayGeneric {
static <T> T[] genericArrayNewInstance(Class<T> componentType) {
return (T[]) Array.newInstance(componentType, 0);
}
public static void main(String args[]) {
int[] intArray;
Integer[] integerArray;
intArray = (int[]) Array.newInstance(int.class, 0);
// Okay!
integerArray = genericArrayNewInstance(Integer.class);
// Okay!
intArray = genericArrayNewInstance(int.class);
// Compile time error:
// cannot convert from Integer[] to int[]
integerArray = genericArrayNewInstance(int.class);
// Run time error:
// ClassCastException: [I cannot be cast to [Ljava.lang.Object;
}
}
Java でジェネリックがどのように機能するかを完全に理解しようとしています。上記のスニペットの 3 番目の割り当てでは、少し奇妙になります。コンパイラは、Integer[]
に変換できないと不平を言っていますint[]
。もちろん、ステートメントは 100% 真実ですが、なぜコンパイラがこの苦情を申し立てているのか疑問に思っています。
その行にコメントを付けて、4 番目の課題のようにコンパイラの「提案」に従うと、コンパイラは実際に満足します!!! これで、コードは正常にコンパイルされます! もちろん、実行時の動作が示唆するように、int[]
に変換できないため、これはクレイジーですObject[]
(これはT[]
実行時に型が消去されるものです)。
だから私の質問は、コンパイラInteger[]
が3番目の割り当ての代わりに割り当てることを「提案」するのはなぜですか? コンパイラはどのようにしてその (誤った!) 結論に達したのでしょうか?
これまでのところ、2 つの回答には多くの混乱があるため、ここで根本的な問題を説明するために別の不可解な例を作成しました。
public class PrimitiveClassGeneric {
static <T extends Number> T test(Class<T> c) {
System.out.println(c.getName() + " extends " + c.getSuperclass());
return (T) null;
}
public static void main(String args[]) {
test(Integer.class);
// "java.lang.Integer extends class java.lang.Number"
test(int.class);
// "int extends null"
}
}
コンパイラが上記のコードをコンパイルできるのは絶対におかしいと思うのは私だけですか?
c.getSuperclass().getName()
たとえば、上記のコードで印刷することは不合理ではありませんT extends Number
。もちろん、今はwhenをgetName()
スローします。NullPointerException
c == int.class
c.getSuperclass() == null
そして私にとって、それはそもそもコードのコンパイルを拒否する十分な理由です。
おそらく究極の狂気:
int.class.cast(null);
そのコードはコンパイルされ、正常に実行されます。