这是不一个如何做事的问题。这是一个为什么的问题。
Java中的数组在运行时知道它们的组件类型,并且由于类型擦除,我们不能拥有泛型类型变量的数组对象。允许并检查涉及泛型的数组类型的声音读/写,唯一的问题似乎是分配器表达式。
请注意,Java编译器也不允许以下内容:
Pong<Integer> lotsofpong [] = new Pong<Integer>[100];
...其中Pong
只是任何旧的参数类。这里没有什么不为人知的。是的,在运行时,lotsofpong
只是Pong
的数组,但我看不出为什么编译器不能记住类型参数以用于编译时的原因。好吧,它确实记得它,因为这些类型存在于编译时,所以唯一的问题似乎是拒绝在编译时给分配器一个特定的涉及泛型参数的组件类型。
即使Pong
的参数是一个通用类型变量,也不应该有所不同。动态数组仍然是Pong
的数组,要求每个元素的大小为Pong
,而不依赖于其类型参数。
是的,我知道有很多方法 - 使用来自非参数类型的强制转换(可能使用SuppressWarning),或使用非参数类的子类Pong<Integer>
并使用该类型。但是有没有理由不允许使用这种分配器?
答案 0 :(得分:1)
基于Zeller提供的链接(基于Josh Bloch - 'Effective Java Book')。
数组不安全,因为以下代码将编译:
String strings [] = {"Foo"};
Object objects [] = strings;
objects[0] = 1;
您将在运行时:java.lang.ArrayStoreException获得特殊异常。 运行时的Java运行时cheks,您将适当的类型放入数组中。
将数组分配给其超类型的数组称为“协方差”。
在编译时中保证泛型是安全的。
如果您在问题中提到的代码段能够编译,则以下代码也会编译:
Pong<Integer> integerPongs [] = new Pong<Integer>[100];
Object objectPongs [] = integerPongs;
objectPongs[0] = new Pong<String>();
Pong<Integer> stringPong = integerPongs[0]; // ClassCastException
我们的代码变得不安全,因此规范禁止使用。
原因:
objectPongs[0] = new Pong<String>();
不抛出java.lang.ArrayStoreException是因为Pong的每个实例的运行时类型总是Pong,因为Generics是编译时机制。 / p>