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