oli*_*ren 37 java generics generic-list generic-collections
有谁知道为什么下面的代码不能编译?add()和addAll()都不能按预期工作.删除"?extends"部分会使一切正常,但之后我将无法添加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
Run Code Online (Sandbox Code Playgroud)
错误1:
IntelliJ说:
add(capture<? extends Foo>) in List cannot be applied to add(Foo)
Run Code Online (Sandbox Code Playgroud)
编译器说:
cannot find symbol
symbol : method addAll(java.util.List<capture#692 of ? extends Foo>)
location: interface java.util.List<capture#128 of ? extends Foo>
Run Code Online (Sandbox Code Playgroud)
错误2:
IntelliJ给了我
addAll(java.util.Collection<? extends capture<? extends Foo>>) in List cannot be applied to addAll(java.util.List<capture<? extends Foo>>)
Run Code Online (Sandbox Code Playgroud)
而编译器只是说
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);
Run Code Online (Sandbox Code Playgroud)
Paŭ*_*ann 55
(我这里假设Bar
和Baz
是两种亚型Foo
.)
List<? extends Foo>
表示某种类型的元素列表,它是Foo的子类型,但我们不知道哪种类型.这种列表的例子是a ArrayList<Foo>
,a LinkedList<Bar>
和a ArrayList<Baz>
.
由于我们不知道哪个亚型是类型参数,我们不能把Foo
对象进去,既不Bar
或Baz
对象.但我们仍然知道type参数是一个子类型Foo
,因此列表中已经存在的每个元素(以及我们可以从列表中获取的元素)必须是一个Foo
对象,所以我们可以使用 Foo f = list.get(0);
和类似的东西.
这样的列表只能用于从列表中取出元素,而不是添加元素(除了null
,但我不知道编译器是否实际允许这样).
甲List<Foo>
另一方面允许添加任何对象,它是一个Foo
对象-与作为Bar
和Baz
是的亚型Foo
,所有Bar
和Baz
对象是Foo
对象,所以它们可以被添加,太.
Mic*_*ers 25
记住PECS:Producer扩展,消费者超级.
由于您尝试将项目添加到list2,因此它是一个使用者,无法声明为List<? extends Foo>
.但是当你将list2添加到list1时,你也将list2用作生产者.因此,list2既是生产者又是消费者,必须是a List<Foo>
.
list1,作为一个纯粹的消费者,可以是一个List<? super Foo>
.
他们是错误的.让我们修改您的代码,考虑到Bar
并Baz
正在扩展两种不同类型Foo
:
List<? extends Foo> list1 = new ArrayList<Bar>();
List<? extends Foo> list2 = new ArrayList<Baz>();
Run Code Online (Sandbox Code Playgroud)
如果list1.add(new Foo())
允许,您可以在包含Bar实例的集合中添加Foo实例.这解释了第一个错误.
如果list1.addAll(list2)
允许,list2中的所有Baz实例都将添加到list1,其中只包含Bar实例.这解释了第二个错误.
归档时间: |
|
查看次数: |
16833 次 |
最近记录: |