本文介绍了带通配符的列表会导致泛型voodoo错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有谁知道为什么下面的代码不能编译? 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错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 22:03