【发布时间】:2013-11-23 22:44:52
【问题描述】:
看下一段代码:
ArrayList<? extends Object> list = new ArrayList<Object>();
list.add(new Object());
它不会编译。问题是为什么?
【问题讨论】:
看下一段代码:
ArrayList<? extends Object> list = new ArrayList<Object>();
list.add(new Object());
它不会编译。问题是为什么?
【问题讨论】:
ArrayList<? extends Object>
和刚才一样
ArrayList<?>
您可以将 any ArrayList 分配给这种类型的变量。例如,
ArrayList<? extends Object> list = new ArrayList<String>();
是合法的。显然,语言语义不允许您将Object 添加到这样的列表中。事实上,除了null 或您直接从列表中检索到的内容之外,他们不会让您添加任何内容。
正如 Lukas 在评论中所指出的,甚至将列表自己的项目添加回它也绝非易事:您需要一个辅助方法来将通配符捕获到命名类型中。
public static void main(String[] args) {
ArrayList<? extends Object> list = new ArrayList<String>();
addOwn(list);
}
static <T> void addOwn(List<T> l) { l.add(l.get(0)); }
【讨论】:
问题在于Foo extends Object 并不意味着Collection<Foo> 可以被视为Collection<Object> 的子类型。这仅仅是因为前者不允许你做后者所做的一切。例如,您不能将Object 添加到Collection<Foo>。使用泛型而不是一些具体的类 Foo 不会改变这一点。
【讨论】:
我认为原因是因为泛型类型不是多态的。当您将 wildcards ? 与 extends 一起使用时,除了 null 之外,您无法在集合中添加任何内容。
下面是一个例子,如果允许的话会发生什么:
Class Car{
}
class A extends Car {
}
class B extends Car{
}
现在你有List<? extends Car>
public void someMethod(List<? extends Car> list){
list.add(new A()); //this is not valid
}
你也可以像这样调用方法:
List<B> someList = new Array:list<B>();
somemethod(someList);
【讨论】: