List<? super T>和之间有什么区别List<? extends T>?
我曾经使用List<? extends T>,但它不允许我添加元素list.add(e),而List<? super T>它.
我对Java泛型如何处理继承/多态性感到困惑.
假设以下层次结构 -
动物(父母)
狗 - 猫(儿童)
所以假设我有一个方法doSomething(List<Animal> animals).根据所有继承和多态的规则,我会假设a List<Dog> 是 a List<Animal>而a List<Cat> 是 a List<Animal>- 所以任何一个都可以传递给这个方法.不是这样.如果我想实现这种行为,我必须明确告诉该方法接受一个Animal的任何子类的列表doSomething(List<? extends Animal> animals).
我知道这是Java的行为.我的问题是为什么?为什么多态通常是隐含的,但是当涉及泛型时必须指定它?
来自Apple的书"结构和类之间最重要的区别之一是结构在代码中传递时总是被复制,但类是通过引用传递的."
任何人都可以让我理解这意味着什么,对我来说,类和结构似乎是一样的.
我有一个List,声明如下:
List<? extends Number> foo3 = new ArrayList<Integer>();
Run Code Online (Sandbox Code Playgroud)
我试图将3添加到foo3.但是我收到如下错误消息:
The method add(capture#1-of ? extends Number) in the type List<capture#1-of ?
extends Number> is not applicable for the arguments (ExtendsNumber)
Run Code Online (Sandbox Code Playgroud) <? super E>和之间有什么区别<? extends E>?
例如,当你看一下类时java.util.concurrent.LinkedBlockingQueue,构造函数有以下签名:
public LinkedBlockingQueue(Collection<? extends E> c)
Run Code Online (Sandbox Code Playgroud)
并为方法之一:
public int drainTo(Collection<? super E> c)
Run Code Online (Sandbox Code Playgroud) 据我所知,它<? super T>代表任何超级类T(T任何级别的父类).但我真的很难想象这个通用绑定通配符的任何现实生活示例.
我明白了什么<? super T>意思,我看过这个方法:
public class Collections {
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个真实生活用例的例子,可以使用这种结构,而不是解释它是什么.
最近,我读了这篇文章:http: //download.oracle.com/javase/tutorial/extra/generics/wildcards.html
我的问题是,而不是创建这样的方法:
public void drawAll(List<? extends Shape> shapes){
for (Shape s: shapes) {
s.draw(this);
}
}
Run Code Online (Sandbox Code Playgroud)
我可以创建一个这样的方法,它工作正常:
public <T extends Shape> void drawAll(List<T> shapes){
for (Shape s: shapes) {
s.draw(this);
}
}
Run Code Online (Sandbox Code Playgroud)
我应该使用哪种方式?在这种情况下,通配符是否有用?
为什么我super只能使用通配符而不使用类型参数?
例如,在Collection界面中,为什么toArray方法不是这样写的
interface Collection<T>{
<S super T> S[] toArray(S[] a);
}
Run Code Online (Sandbox Code Playgroud) 虽然
Integer是子类型Number,但List<Integer>不是子类型List<Number>,实际上这两种类型并不相关.的共同的父
List<Number>和List<Integer>是List<?>.
我的问题是关于第二句话.我们怎么能说List<?>是共同的父母List<Number>和List<Integer>?
?代表未知类型,可以是任何引用类型.就算我说?会Object在这里,Object是共同的父母Integer和Number并不意味着List<Object>成为一个共同的父List<Integer>和List<Number>.
有谁知道为什么下面的代码不能编译?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 …Run Code Online (Sandbox Code Playgroud) generics ×9
java ×9
inheritance ×3
polymorphism ×2
super ×2
api ×1
collections ×1
generic-list ×1
swift ×1