问题描述
有谁知道为什么下面的代码不能编译? add()和addAll()都不按预期工作。删除?extends部分会使所有的工作都正常,但是我不能添加Foo的子类。
?延伸Foo> list1 = new ArrayList< Foo>();列表< ;?延伸Foo> list2 = new ArrayList< Foo>();
* *不会编译* /
list2.add(new Foo()); //错误1
list1.addAll(list2); //错误2
错误1:
IntelliJ说:
在列表中添加(capture<?extends Foo>)不能应用于添加(Foo)
编译器说:
找不到符号
symbol:方法addAll(java.util.List< capture#692 of?extends Foo>)
location:interface java.util.List< capture#128 of?延伸Foo>
错误2:
IntelliJ给了我
列表中的addAll(java.util.Collection< ;?扩展捕获<?extends Foo>>)不能应用于addAll (java.util.List< capture<?extends Foo>>)
找不到符号
symbol:method addAll(java.util.List< capture#692 of?extends Foo> )
location:interface java.util.List< capture#128 of?延伸Foo>
list1.addAll(list2);
Bar 和 Baz
都是 Foo
的子类型。)
列表< ;?扩展Foo>
表示某种类型的元素列表,这是Foo的子类型,但我们不知道哪种类型。这样的列表的例子是 ArrayList< Foo>
,a LinkedList< Bar>
和 ArrayList< Baz>
。
由于我们不知道哪个子类型是类型参数,我们不能把 Foo
对象,既不是 Bar
或 Baz
对象。但是我们仍然知道type参数是 Foo
的子类型,所以列表中的每个元素(以及我们可以从列表中获得的)都必须是 Foo
对象,所以我们可以使用 Foo f = list.get(0);
和类似的东西。
这样的列表只能用于从列表中取出元素,而不是添加元素(除了 null
,但我不知道编译器是否真的允许这样做)。另一方面,
A List< Foo>
允许添加任何 Foo
对象 - 并作为 Bar
和 Baz
的子类型是 Foo
,所有 Bar
和 Baz
对象是 Foo
对象,因此它们也可以添加。
Does anyone know why the following code does not compile? Neither add() nor addAll() works as expected. Removing the "? extends" part makes everything work, but then I would not be able to add subclasses of Foo.
List<? extends Foo> list1 = new ArrayList<Foo>();
List<? extends Foo> list2 = new ArrayList<Foo>();
/* Won't compile */
list2.add( new Foo() ); //error 1
list1.addAll(list2); //error 2
error 1:
IntelliJ says:
add(capture<? extends Foo>) in List cannot be applied to add(Foo)
The compiler says:
cannot find symbol
symbol : method addAll(java.util.List<capture#692 of ? extends Foo>)
location: interface java.util.List<capture#128 of ? extends Foo>
error 2:
IntelliJ gives me
addAll(java.util.Collection<? extends capture<? extends Foo>>) in List cannot be applied to addAll(java.util.List<capture<? extends Foo>>)
Whereas the compiler just says
cannot find symbol
symbol : method addAll(java.util.List<capture#692 of ? extends Foo>)
location: interface java.util.List<capture#128 of ? extends Foo>
list1.addAll(list2);
(I assume here that Bar
and Baz
are both subtypes of Foo
.)
List<? extends Foo>
means a list of elements of some type, which is a subtype of Foo, but we don't know which type. Examples of such lists would be a ArrayList<Foo>
, a LinkedList<Bar>
and a ArrayList<Baz>
.
As we don't know which subtype is the type parameter, we can't put Foo
objects into it, neither Bar
or Baz
objects. But we still know that the type parameter is a subtype of Foo
, so every element already in the list (and which we can get from the list) must be a Foo
object, so we can use Foo f = list.get(0);
and similar things.
Such a list can only be used for taking elements out of the list, not to adding elements at all (apart from null
, but I don't know if the compiler actually allows this).
A List<Foo>
on the other hand allows adding any object which is a Foo
object - and as Bar
and Baz
are subtypes of Foo
, all Bar
and Baz
objects are Foo
objects, so they can be added, too.
这篇关于带通配符的列表会导致泛型voodoo错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!