为什么这段代码会编译:
ArrayList strings = new ArrayList();
strings.add("s1");
strings.add("s2");
ArrayList<Integer> numbers = new ArrayList<Integer>(strings);
鉴于有问题的构造函数需要Collection<? extends E>
,其中E
在这种情况下是整数?原始类型ArrayList
中包含的对象如何成为E
的子类?或者是否有一些隐藏的编译器魔法可以将其用于遗留目的?
答案 0 :(得分:2)
检查ArrayList
构造函数:
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
elementData
是对象数组:
transient Object[] elementData;
所以新ArrayList(Collection<? extends E> c)
会接受所有Collection
,不关心E
类型
我们使用它时会抛出ClassCastExceptionwhen
:
Integer i= numbers.get(1);
答案 1 :(得分:1)
编译器应该给你这个警告:
类型安全性:ArrayList类型的表达式需要取消选中 转换为符合
Collection<? extends Integer>
说给定的参数(字符串)有问题。
尝试运行代码时也应该得到此异常:
java.lang.ClassCastException:java.lang.String无法强制转换为 java.lang.Integer中
没有编译错误的原因是没有正确定义ArrayList字符串,省略了String类型。所以编译可能只是猜测有什么东西。将您的代码更改为
ArrayList<String> strings = new ArrayList<String>();
你将得到编译错误
构造函数
ArrayList<Integer>(ArrayList<String>)
未定义