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 中是如何工作的。在上面代码片段的第三个赋值中,事情对我来说有点奇怪:编译器抱怨Integer[]
无法转换为int[]
. 当然,该声明是 100% 正确的,但我想知道为什么编译器会提出此投诉。
如果您注释该行,并按照编译器的“建议”进行第四次赋值,编译器实际上是满意的!!! 现在代码编译得很好!当然,这很疯狂,因为就像运行时行为所暗示的那样,int[]
无法转换为Object[]
(这是T[]
在运行时类型擦除的内容)。
所以我的问题是:为什么编译器“建议”我分配给Integer[]
第三次分配?编译器是如何得出这个(错误的!)结论的?
到目前为止,这两个答案存在很多混淆,因此我创建了另一个令人费解的示例来说明这里的潜在问题:
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
. 当然现在getName()
会扔的NullPointerException
时候c == int.class
,既然c.getSuperclass() == null
。
对我来说,这是拒绝编译代码的一个很好的理由。
也许是终极疯狂:
int.class.cast(null);
该代码编译并运行良好。