我有点困惑Java泛型Java泛型混乱
下面是代码
class Base{}
class Derived extends Base{}
我们可以实例化这样
List<? extends Base> list = new ArrayList<Base>();
列表为什么我不能添加迈上了一个新这样的项目
list.add(new Base());
所以用户不能像通配符那样使用“add”方法?在遗传学类型?
谢谢
我有点困惑Java泛型Java泛型混乱
下面是代码
class Base{}
class Derived extends Base{}
我们可以实例化这样
List<? extends Base> list = new ArrayList<Base>();
列表为什么我不能添加迈上了一个新这样的项目
list.add(new Base());
所以用户不能像通配符那样使用“add”方法?在遗传学类型?
谢谢
PECS - 生产者延伸,超级消费者。
如果用替换为super
,则可以添加new Base()
。
List<? extends Base>
的意思是“保存库(或Base
本身)的任意子类的实例列表。但如果你想它不能容纳两个不同的子类的实例。
列表持有Base
和Derived
,然后用List<Base>
,但请注意,它不能晚投地List<Derived>
就让它
List<Base> list = new ArrayList<Base>();
,则不应使用WIL dcards当你知道实际的类型时......只是当你提供某种未知类型的东西时。
在这种情况下,? extends Base
意味着List
只允许包含某个特定的子类型Base
,但您不知道是哪个子类型。因此,除了null
之外,您无法添加任何内容。
你可以尝试阅读?
的东西:
List<? extends Base>
这是 “东西延伸Base
List
”。所以,很显然,你不能添加一个Base
(就像即使String
延伸Object
您不能添加一个Object
到List<String>
什么,你可以在你的情况做的是:
List<? super Base>
这是“的东西是由Base
”扩展List
。所以,你可以添加一个Base
那里(就像你可以在String
添加到List<Object>
,因为Object
由String
延长。
我认为这是一个Java泛型的设计。编译通配符? extends Base
意味着集合引用可以指向一个集合对象,该集合对象可以包含扩展Base的任何(和全部)类型。你可以这样写,以及:
List<? extends Base> _listBaseSubtypes = new ArrayList<Derived>();
现在,上述行,如果你想想看,以下将是明显的错误:
_listBaseSubtypes.add(new Base());
我认为Java设计者决定允许第一行代码有效。为了避免第二行代码可能导致的运行时错误,它在编译时被捕获。
话虽如此,想到的问题是:什么类型的对象应该被允许添加到集合中,因为实际的集合对象可以是任何派生类型的集合?
因为您可以根据需要派生尽可能多的类型,并且找不到与实际集合对象中保存的类型兼容的单一类型(请记住,集合对象可以声明为保存'任何'派生类型),问题的简单答案是:无。因此,不能通过添加接口将任何对象添加到集合中,因为对于任何可能尝试传入add方法的对象,都会出现编译器异议,因为此类型与实际类型不兼容集合对象成立。
这个缩写本身并不是很有用;有关详细信息,请参阅[此SO问题](http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs)。 – Pops 2011-04-27 21:49:12
@ Tordamus阁下 - 是的,我已经在扩大我的答案以添加正确的解释。 – Bozho 2011-04-27 21:49:55
但是将类型声明为List <?当你正在给它分配一个'ArrayList '时,超级Base>'没有任何意义。通配符适用于当您不知道确切的类型参数时,因为它是从别处提供的。 –
ColinD
2011-04-27 21:50:02