在Java源代码中,为什么ArrayList.add的参数为泛型类型T而addAll的参数为泛型类型<? 扩展 E>?

Lak*_*ita 1 java generics

这是Java的源代码ArrayList(使用java 1.8)

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
Run Code Online (Sandbox Code Playgroud)
public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
}
Run Code Online (Sandbox Code Playgroud)

我不是很清楚为什么我们只能使用Eforadd()而我们可以使用<? extends E>foraddAll()

luk*_*302 6

因为如果你有 anArrayList<Number>你可以adda Integerto it 和 a Numberand aDouble因为它们都是E/ 的子类型Number但是你不能addAllaArrayList<Integer>如果签名是addAll(Collection<E> c)因为 anArrayList<Integer>不是(的子类型)ArrayList<Number>因为在 Java 泛型是不变的。仅当您将其定义为时,您addAll(Collection<? extends E> c)才能添加具有更具体通用子类型的列表。这基本上意味着“任何具有作为子类型的泛型参数的集合E