名单<! - ? extends Object - > #add(new MyClass())不编译

时间:2012-12-11 17:10:02

标签: java generics extends

MyClass e = new MyClass();

List<Object> ok = new ArrayList<Object>();
List<? extends Object> ko = new ArrayList<Object>();

ok.add(e);
ko.add(e); // doesn't compile

为什么不编译? MyClassObject ...

的子类

有关信息,我收到以下消息:

The method add(capture#1-of ? extends Object) in the type List<capture#1-of ? extends Object> is not applicable for the arguments (MyClass)

2 个答案:

答案 0 :(得分:7)

这是你的问题:

List<? extends Object>

这意味着“它是某个类型T的列表,它扩展了Object,但我不关心T是什么”。

所以这是有效的:

List<? extends Object> ko = new ArrayList<Banana>();

...但你不想要:

ko.add(e);

在那时编译,不是吗?因为MyClass不是Banana

请参阅Java generics FAQ了解更多的更多信息。

答案 1 :(得分:1)

Effective Java 中的Josh Block教我们 PECS :Producer = extends,Consumer = super

由于您使用ko作为使用者(您向其添加了一个对象),因此您应声明为:

List<? super Object> ko = new ArrayList<Object>();

或许可以更好地说明这个概念:

List<? super MyClass> ko = new ArrayList<Object>();

您可能会想到它只能将MyClass对象分配给类型为MyClass的变量或任何超类型 - 您只能将MyClass对象添加到类型为MyClass的List中,或者任何超级类型。

回到你的例子,List<? extends Object> ko不能成为正确的类型声明,因为它也会接受这个:

List<? extends Object> ko = new ArrayList<String>();

您在此处看到,基于ko的泛型类型,编译器无法确定实际列表是否接受MyClass的实例。