<?超级E>和<?扩展列表的 E>

2022-09-02 21:43:51

具有以下简单的类结构:

class A {
}

class B extends A {
}

class C extends B {
}

我正在创建一个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>();

对于每个列表,我尝试为每个早期创建的类添加1个对象:A,B,C。唯一可能的组合是:

  • 将类 A、B、C 的对象添加到列表 4

  • 将 B 类和 C 类的对象添加到列表5

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

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

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


答案 1

"?扩展 A“表示”从 A(或 A 本身)派生的某种类型”。例如,a 是兼容的 - 但你不应该能够将 a 添加到这样的列表中 - 它意味着是一个 !您所知道的是,您列表中获取的任何内容都将是某种类型的。List<ByteArrayOutputStream>List<? extends OutputStream>FileOutputStreamList<ByteArrayOutputStream>OutputStream

"?super A“的意思是”某种类型,它是A(或A本身)的超类”。例如,a 与 兼容。你绝对可以向这样的列表添加一个 - 但是如果你从列表中获取一个项目,你无法真正保证它。List<OutputStream>List<? super ByteArrayOutputStream>ByteArrayOutputStream

请参阅Angelika Langer的Generics FAQ以获取更多信息。


答案 2

类型定义不适用于可变列表 - Java 泛型中给出的解释 Java 泛型 Pdf List<? extends A>

add() 方法采用类型 E(集合的元素类型)的参数。当实际类型参数为 ?时,它代表某个未知类型。我们传递到添加的任何参数都必须是此未知类型的子类型。由于我们不知道那是什么类型,因此我们无法传入任何内容。

但是,当 typedef 是 type 参数时?是隐式类型的。List<? super A>


推荐