参数化类型的数组

时间:2012-03-03 00:03:00

标签: java generics

我无法确定以下

的RHS预期的类型参数
ArrayList<Pair<ParseNode,ParseNode>>[] nodes = new ArrayList[indexes.length];

为什么<Pair<ParseNode,ParseNode>>的副本不合法?

3 个答案:

答案 0 :(得分:9)

混凝土参数化阵列的数组固有地被打破。记住数组是协变的,数组类型检查是运行时操作。在运行时,所有泛型都已被类型擦除,因此阵列存储检查无法告诉<Pair<ParseNode, ParseNode>> <Pair<BigInteger,IOException>>

泛型的基本契约是“我,编译器,承诺如果你编写的代码不会产生警告,你就永远不会在运行时获得类转换异常。”

如果不是ArrayList<Pair<ParseNode,ParseNode>>的内容被放入该数组,编译器也不能保证它能够给你一个编译时错误。如果添加错误的类型,运行时系统也不能保证你会得到一个ArrayStoreException(就像语言规范所说的那样),而不是稍后当你把它取出时的ClassCastException。 (第二部分实际上是为什么它实际上是非法的而不仅仅是一个警告,它会导致一个不符合语言规范的数组。)

因此,它不允许您以这种方式声明它们并迫使您承认“不安全”警告。这样它就说“我告诉过你我无法保证不会因为使用这个数组而导致任何类别转换异常,而是确保你只在这里放置正确的东西。”

答案 1 :(得分:5)

Java不支持通用数组。数组是协变的,泛型不是。这意味着如果A类扩展了B类,那么A []也是B []。和代码

A[] a = new A[10];
B[] b = a;

是合法的。

但是对于仿制药来说并不相同。即使T扩展为X,也无法将Foo<T>分配给Foo<X>。因此Foo<T>[]的元素无法保证类型安全。

修改 请原谅我只是链接,但我发现了Java theory and practice: Generics gotchas文章,它解释了关于数组协方差的一切比我梦想的更好。

答案 2 :(得分:0)

不要使用数组。使用另一个ArrayList。

ArrayList<List<Pair<ParseNode,ParseNode>>> listOfLists = new ArrayList<List<Pair<ParseNode,ParseNode>>>();

listOfLists.add(new ArrayList<<Pair<ParseNode,ParseNode>>());