【发布时间】:2012-03-21 11:23:15
【问题描述】:
我无法确定以下 RHS 预期的类型参数
ArrayList<Pair<ParseNode,ParseNode>>[] nodes = new ArrayList[indexes.length];
为什么<Pair<ParseNode,ParseNode>> 的副本不合法?
【问题讨论】:
我无法确定以下 RHS 预期的类型参数
ArrayList<Pair<ParseNode,ParseNode>>[] nodes = new ArrayList[indexes.length];
为什么<Pair<ParseNode,ParseNode>> 的副本不合法?
【问题讨论】:
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 文章,它比我想象的更好地解释了有关数组协方差的一切。
【讨论】:
具体参数化类型的数组本身就被破坏了。记住数组是协变的,数组类型检查是一个运行时操作。在运行时,所有泛型都已被类型擦除,因此数组存储检查无法区分 <Pair<ParseNode, ParseNode>> 和 <Pair<BigInteger,IOException>>。
泛型的基本约定是“我,编译器,承诺如果您编写的代码不会产生警告,您将永远不会在运行时遇到类转换异常。”
编译器也不能向您保证,如果将不是 ArrayList<Pair<ParseNode,ParseNode>> 的东西放入该数组中,它将能够给您一个编译时错误。如果您添加了错误的类型,运行时系统也不能保证您将获得 ArrayStoreException(就像语言规范所说的那样),而不是稍后在您将其取出时获得 ClassCastException。 (第二部分真的是为什么它实际上是非法的,而不仅仅是一个警告,它会导致一个不符合语言规范的数组。)
因此它不允许您以这种方式声明它们并强制您承认“不安全”警告。这样它就说“我告诉过你,我不能保证不会因为使用这个数组而出现任何类转换异常,你必须确保在这里只放正确的东西。”
【讨论】:
不要使用数组。使用另一个 ArrayList。
ArrayList<List<Pair<ParseNode,ParseNode>>> listOfLists = new ArrayList<List<Pair<ParseNode,ParseNode>>>();
listOfLists.add(new ArrayList<<Pair<ParseNode,ParseNode>>());
【讨论】: