具有以下简单的类结构:
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的对象添加到list4
将B类和C类的对象添加到list5
将C类对象添加到列表list6中。 其余的尝试给出了编译器错误,例如:
方法添加(捕获#1-of?extends A)类型列表不适用于 参数(A)
为什么我不能将A,B,C类的任何对象添加到list1 / 2/3? 为何... list4接受类A,B,C的对象,如果它们应该是A类的超类,因为list4是定义的吗?
答案 0 :(得分:14)
“?extends A”表示“某种类型派生自A(或A本身)”。例如,List<ByteArrayOutputStream>
与List<? extends OutputStream>
兼容 - 但您不应该将FileOutputStream
添加到此类列表中 - 它应该是List<ByteArrayOutputStream>
!你所知道的是,你从列表中获取的任何东西都是某种OutputStream
。
“?super A”表示“某种类型,它是A(或A本身)的超类”。例如,List<OutputStream>
与List<? super ByteArrayOutputStream>
兼容。你绝对可以在这样的列表中添加ByteArrayOutputStream
- 但如果你从列表中获取一个项目,你就无法真正保证它。
有关详情,请参阅Angelika Langer's Generics FAQ。
答案 1 :(得分:4)
类型定义List<? extends A>
不适用于可变列表 - Java泛型Java Generics Pdf 中给出的解释是
add()方法接受E类型的参数,即元素类型 采集。 当实际类型参数为?时,它代表某种未知类型。 任何参数 我们传递给add必须是这个未知类型的子类型。因为我们 不知道 什么类型,我们不能传递任何东西。
但是,当typedef为List<? super A>
时,那么类型参数?隐式输入。
答案 2 :(得分:2)
List<? extends A> list1
它是一个列表,其type元素可以是A的任何未知子类。例如,它可以是D子类。因此,你不能添加任何东西,它可能是错误的......
List<? super A> list4
它是一个列表,其类型元素可以是A,或者是A的超类(在这种情况下不存在,除了Object)。因此,您可以向其添加A对象,或者添加A的任何子类,例如B或C.
答案 3 :(得分:1)
这不起作用。
创建函数时应该使用<? extends T>
哪个参数是某种类型的未知子类型的集合,并且您想要从该集合中获取对象:
int sum(Collection<? extends Integer> collection) {
for (Integer : collection) {
// do sth
}
// ...
}
您无法向此集合添加新项目,因为您不知道此集合包含哪种具体类型。您所知道的是,该类型扩展了Integer
。
如果要将<? super T>
类型的新项目添加到集合并返回该集合,则使用T
,但是您无法保证可以从中检索的内容,并且必须转换{的结果{1}}或检查其类型。您可以安全地添加get()
类型和子类型的项目,并检索T
类型的项目。
答案 4 :(得分:0)
List<? super B>
允许您使用任何超类型B的列表,即list5 = new ArrayList&lt; A &gt;();
或list5 = new ArrayList&lt; Object &gt;();
你可以安全地将B(和子类型)添加到使用B超类型的每个列表中,但是你不能添加任何超类型的B.想象一下:
public void myAdd(List<? super B> lst) {
lst.add(new Object()) //this is a supertype of B (compile time error)
}
...
ArrayList<A> list = new ArrayList<A>();
myAdd(list); //tries to add Object to a list of type A