1

不是如何做事的问题。这是一个为什么会这样的问题。

Java 中的数组在运行时知道它们的组件类型,并且由于类型擦除,我们不能拥有泛型类型变量的数组对象。允许并检查涉及泛型的数组类型的声音读/写,唯一的问题似乎是分配器表达式。

请注意,Java 编译器也不允许以下内容:

Pong<Integer> lotsofpong [] = new Pong<Integer>[100];

...Pong任何旧的参数类在哪里。这里没有什么是未知的。是的,在运行时,lotsofpong它只是一个数组Pong,但我看不出编译器无法记住编译时类型参数的原因。好吧,它确实记得它,因为这些类型在编译时就存在,所以唯一的问题似乎是在编译时拒绝给分配器一个特定的涉及泛型参数的组件类型。

即使参数 ofPong是一个泛型类型变量,也不应该有所作为。动态数组仍然是 的数组Pong,每个元素需要 a 的大小Pong,这不依赖于其类型参数。

是的,我知道有一些方法可以解决它 - 要么使用非参数类型的强制转换(可能使用 SuppressWarning),要么使用非参数类的子Pong<Integer>类并改用该类型。但是为什么不允许这种分配器是有原因的吗?

4

1 回答 1

1

基于 Zeller 提供的链接(基于 Josh Bloch - 'Effective Java Book')。

数组不安全,因为以下代码将编译:

String strings [] = {"Foo"};
Object objects [] = strings;
objects[0] = 1;

你会在运行时得到一个特殊的异常:java.lang.ArrayStoreException。Java 运行时会在运行时检查您将适当的类型放入数组中。

将数组分配给其超类型数组称为“协方差”。

泛型在编译时保证是安全的。

如果您在问题中提到的代码片段能够被编译,则以下代码也将编译:

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,因为泛型是一种编译时机制。

于 2013-05-27T08:37:14.233 回答