<?超级E>和<?扩展E> for List

qba*_*uak 18 java generics

具有以下简单的类结构:

class A {
}

class B extends A {
}

class C extends B {
}
Run Code Online (Sandbox Code Playgroud)

我正在创建一个ArrayList来保存先前创建的类的对象:

List<? extends A> list1 = new ArrayList<A>();
List<? extends B> list2 = new ArrayList<B>();
List<? extends C> list3 = new ArrayList<C>();

List<? super A> list4 = new ArrayList<A>();
List<? super B> list5 = new ArrayList<B>();
List<? super C> list6 = new ArrayList<C>();
Run Code Online (Sandbox Code Playgroud)

对于每个列表,我正在尝试添加每个先前创建的类的1个对象:A,B,C.唯一可能的组合是:

  • 将类A,B,C的对象添加到list4

  • 将类B和C的对象添加到list5

  • 将类C的对象添加到列表list6.其余的尝试给出了编译器错误,例如:

类型List中的方法add(capture#1-of?extends A)不适用于参数(A)

为什么我不能将类A,B,C的任何对象添加到list1/2/3?为什么例如list4接受类A,B,C的对象,如果它们应该是A类的超类,因为list4是定义的?

Jon*_*eet 14

"?extends A"表示"某种类型派生自A(或A本身)".因此,例如,a List<ByteArrayOutputStream>兼容List<? extends OutputStream>- 但你不应该能够添加FileOutputStream到这样的列表 - 它应该是一个List<ByteArrayOutputStream>!你所知道的是,你列表中获取的任何东西OutputStream都是某种形式.

"?super A"表示"某种类型,它是A(或A本身)的超类".例如,a List<OutputStream>兼容List<? super ByteArrayOutputStream>.你绝对可以添加ByteArrayOutputStream到这样的列表 - 但如果你从列表中获取一个项目,你不能真正保证它.

有关更多信息,请参阅Angelika Langer的Generics FAQ.