为什么 ArrayList<E> 构造函数允许原始 ArrayList 参数



为什么这段代码可以编译:

ArrayList strings = new ArrayList();
strings.add("s1");
strings.add("s2");
ArrayList<Integer> numbers = new ArrayList<Integer>(strings);

假设构造函数期望Collection<? extends E>,其中E在这种情况下是整数?原始类型ArrayList中包含的对象如何成为E的子类?或者有一些隐藏的编译器魔力允许这用于遗留目的?

检查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);

编译器会给你这样的警告:

类型安全:不检查ArrayList类型的表达式转换为符合Collection<? extends Integer>

表示给定的参数(字符串)有问题。

你也应该得到这个异常时,试图运行代码:

. lang。ClassCastException: java.lang.String不能强制转换为java.lang.Integer

你没有得到编译错误的原因是数组列表字符串没有正确定义,你省略了String类型。所以编译器可能只是猜测出了什么问题。将代码更改为

ArrayList<String> strings = new ArrayList<String>();

,你会得到编译错误

构造函数ArrayList<Integer>(ArrayList<String>)是undefined

相关内容

最新更新