创建类型对象的通用列表并添加字符串

时间:2013-10-02 18:50:47

标签: java generics

我正在尝试创建一个通用列表,它将包含从Object继承的任何类型的项(我假设每个对象都是object类型)。

但是,在下面的例子中,当我尝试添加一个String(从Object继承)时,它在Eclipse中显示错误

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


List<? extends Object> alist = new ArrayList<Object>();
alist.add("USA");

有人可以解释为什么我会收到此错误吗?

5 个答案:

答案 0 :(得分:6)

原因是<? extends Object>可以代表Object的任何子类,这可能与String无关。它可能是List<Integer>

List<? extends Object> alist = new ArrayList<Integer>();  // works
alist.add("USA");  // Should you be allowed to do this?  No!

对于类型安全,您应该无法执行此类add操作。因此,不允许此操作。

解决方法是在变量声明中消除通配符:

List<Object> alist = new ArrayList<Object>();

现在任何Object或子类都可以传递给add

答案 1 :(得分:0)

您正在尝试的问题是以下

List<? extends Object> alist = getList(); // returns a List<Dog>
alist.add("USA"); // would fail at runtime

因此,编译器不允许您添加到通配符绑定的任何List

答案 2 :(得分:0)

古怪的短语? extends Object意味着它也没关系 使用任何类型的元素作为Object的子类型添加集合的所有成员。

由于所有类型都继承了Object,因此您只需编写List<Object>

List<Object> alist = new ArrayList<Object>();
alist.add("USA");

答案 3 :(得分:0)

您需要<? super String>将字符串或其中的任何超类添加到列表iirc中。或者只是<?>

请参阅下限边界通配符:http://docs.oracle.com/javase/tutorial/java/generics/lowerBounded.html

答案 4 :(得分:0)

您的案例是Effective Java的 PECS助记符可能有用的另一个例子。

您的alist是消费者,意味着您希望它(消费)添加新对象。那么,从PECS开始,您应该使用Collection<? super Thing>

List<? super Object> alist = new ArrayList<Object>();
alist.add("USA");

这样,您始终可以.add()任意Object进入alist。 (因为"USA"Object,您可以毫无问题地添加它。)

请注意,在您的类型中使用super ...

List<? super Object> alist = new ArrayList<Integer>(); // notice <Integer> here
alist.add("USA");

...第一行会合理地产生错误,因为Integer不是Object的超类型。

当然,这很有点令人困惑,因为Object没有超类,没有类是Object的超类。因此,有效地,List<? super Object> alist =赋值的唯一可能的右侧是List<Object>(或由于多态性而实现List的任何类)。

Read more about PECS here

阅读book Effective Java here中的PECS说明。