1

下面的代码:

List<? extends String> genericNames = new ArrayList<String>();
genericNames.add("John");

给出编译器错误:

此行有多个标记 - List 类型中的方法 add(capture#1-of ? extends String) 不适用于参数 (String) - List 类型中的方法 add(capture#1-of ?) 不适用适用于参数(字符串)

是什么导致了这个错误?由于我在类型参数中扩展字符串,我是否应该无法添加字符串或其子类型?

4

3 回答 3

12

当您使用带扩展的通配符时,除了null之外,您不能在集合中添加任何内容。此外,String 是最终类;没有什么可以扩展字符串。

原因:如果允许,您可能只是将错误的类型添加到集合中。

例子:

class Animal {

}

class Dog extends Animal {

}

class Cat extends Animal {

}

现在你有List<? extends Animal>

public static void someMethod(List<? extends Animal> list){
    list.add(new Dog()); //not valid
}

你调用这样的方法:

List<Cat> catList = new ArrayList<Cat>(); 
someMethod(catList);

如果允许在使用带扩展的通配符时添加到集合中,您只需将 Dog 添加到仅接受 Cat 或子类型类型的集合中。因此,您不能将任何内容添加到使用具有上限的通配符的集合中。

于 2012-12-21T16:30:53.597 回答
1

只想添加到 GanGnaMStYleOverFlow 的答案,您可以将任何子类型的对象添加Animal到以下列表中:

List<Animal> animals = new ArrayList<Animal>();

每当您认为它可以包含任何种类的动物时,您都应该使用此类列表。

另一方面,List<? extends Animal>当您想指定列表包含某种动物但您不知道是哪一种时,您应该使用。由于您不知道那里有哪些动物,因此您无法添加任何动物。

于 2012-12-21T16:53:55.353 回答
1

String是最终类,不能扩展。此外,对于您似乎感兴趣的情况,您不需要 extends 关键字。 List<String>会做你想做的事。这将允许 Strings 和 String 的子类(如果这样的东西可能存在,它不能因为 String 是最终的)。

于 2012-12-21T16:47:12.067 回答