我正在尝试创建一个通用列表,它将包含从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");
有人可以解释为什么我会收到此错误吗?
答案 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
的任何类)。
阅读book Effective Java here中的PECS说明。