我有一个Java类,其中包含扩展MyClass的对象的子项。
class MyClass {
List<? extends MyClass> items;
[...]
由于某种原因,我无法在此列表中插入 MyClass 项目。我不明白为什么,以及如何绕过这个问题。例如:
void foo(){
items = new LinkedList<MyClass>(); // This is OK
items.add(new MyClass()); // Not allowed... why?
}
编译器说“ 列表类型中的方法add(capture#1-of?extended MyClass)不适用于参数(MyClass )”
我真的不明白如何绕过此问题,以及为什么编译器应仅接受必须扩展 MyClass 的类型。
注意:为什么我需要使用这种方法?因为我需要允许扩展MyClass才能有子项列表。
答案 0 :(得分:6)
List<? extends MyClass> items
表示type参数为未知类型,可分配给MyClass
。
例如,它可能是List
中的MySubClass
:
public MySubClass extends MyClass{}
List<? extends MyClass> items = new ArrayList<MySubClass>();
现在考虑您也拥有MyAnotherSubClass
的{{1}}:
MyClass
很显然,public MyAnotherSubClass extends MyClass{}
MyClass item = new MyAnotherSubClass(); // refer it using MyClass
不应包含List<MySubClass>
:
MyAnotherSubClass
答案 1 :(得分:4)
声明
List<? extends MyClass> items;
说items
是一个List
,其类型参数并不确定,但可以是MyClass
或子类。
请仔细阅读。它解释了为什么向这样的List
中添加任何内容是不安全的:其类型参数为 unknown 。如果恰好是MySubClass1
,则添加MyClass
或MySubClass2
是不正确的。如果恰好是MySubClass2
,则添加MySubClass1
是不正确的。完全没有可以安全添加的类型。
如果您想为List
添加类型MyClass
的对象以及MyClass
的任何子类的对象,那么您可能只是在寻找List<MyClass>
从技术上讲,List<? super MyClass>
也可以达到特定的目的,但是您会遇到相反的问题:假定列表元素是比{{1}更具体的类型,这在类型上是不安全的。 }。
答案 2 :(得分:1)
使用extends
只能从集合中获取。你不能放进去。您可以使用super
来完成。
因此,就您而言,如果您使用-List<? super MyClass> items;
,则不会收到任何编译/运行时错误。
尽管super允许获取和放置,但获取期间的返回类型为? super T
。