Javagenerics的types参数中的问号是什么意思?

这是从斯坦福分析器附带的一些例子中抽取的一小段代码。 我已经用Java开发了大约4年,但是从来没有对这种代码风格应该表明什么有很深刻的理解。

List<? extends HasWord> wordList = toke.tokenize(); 

我并不担心代码的细节。 我感到困惑的是,这个genericsexpression应该用英语来expression。

谁可以给我解释一下这个?

 ? extends HasWord 

意思是“扩展HasWord类/接口”。 换句话说, HasWord本身或它的任何子…基本上任何可以用instanceof HasWordnull

更技术性地说, ? extends HasWord ? extends HasWord是一个有界的通配符,在第134页开始的Effective Java第2版的第28项中有介绍。这是作为PDF在线提供的generics一章的一部分。

更新:由于Oracle删除了一段时间,PDF链接已经更新。 现在指向伦敦玛丽皇后大学电子工程与计算机科学学院的副本。

更新2:让我们进一步了解一下你为什么要使用通配符。

如果你声明一个方法的签名期望你在List<HasWord>传递,那么你唯一可以传递的就是一个List<HasWord>

但是,如果签名是List<? extends HasWord> List<? extends HasWord>然后你可以传递一个List<ChildOfHasWord>来代替。

请注意List<? extends HasWord>之间有一个微妙的区别 List<? extends HasWord>List<? super HasWord> List<? super HasWord> 。 正如Joshua Bloch所说:PECS =生产者延伸,超级消费者。

这意味着如果你传入一个你的方法从中获取数据的集合(即集合正在生成要使用的方法的元素),则应该使用extends 。 如果你传入一个你的方法添加数据的集合(即集合正在消耗你的方法创build的元素),它应该使用super

这可能听起来很混乱。 但是,您可以在Listsort命令中看到它(这只是Collections.sort的两个版本的快捷方式)。 而不是采取一个Comparator<T> ,它实际上需要一个Comparator<? super T> Comparator<? super T> 。 在这种情况下,比较器消耗List中的元素,以重新sorting列表本身。

问号是“任何types”的指示符。 ? 单独的手段

任何types的扩展Object (包括Object

而上面的例子意味着

任何扩展或实现HasWordtypes(包括HasWord如果HasWord是非抽象类)

List<? extends HasWord> List<? extends HasWord>接受任何扩展HasWord的具体类。 如果你有以下课程…

 public class A extends HasWord { .. } public class B extends HasWord { .. } public class C { .. } public class D extends SomeOtherWord { .. } 

wordList只能包含As或Bs或两者混合的列表,因为这两个类扩展了相同的父HasWorldnull (它没有检查HasWorld )。

也许一个人为的“现实世界”的例子会有所帮助。

在工作中,我们有不同口味的垃圾桶。 所有垃圾箱都装有垃圾,但有些垃圾箱是专门的垃圾箱,不要带任何垃圾。 所以我们有Bin<CupRubbish>Bin<RecylcableRubbsih> 。 types系统需要确保我不能将我的HalfEatenSandwichRubbish放入这两种types的任何一种,但是它可以进入一个普通的垃圾桶“Bin” . If I wanted to talk about a . If I wanted to talk about a垃圾桶which may be a specialist so I can't put in incompatible rubbish, then that would be斌。

(注意: ? extends并不意味着只读,例如我可以采取适当的预防措施从一个未知专业的垃圾箱中取出一块垃圾,然后把它放回另一个地方。)

不知道有多大的帮助。 存在多态性的指针指针并不是完全明显的。

用英语:

它是扩展HasWord类的一些types的List ,包括HasWord

一般来说? 在generics中是指任何类。 而extends SomeClassextends SomeClass指定该对象必须扩展SomeClass (或者是该类)。

问号用于定义通配符 。 查看关于他们的Oracle文档: http : //docs.oracle.com/javase/tutorial/java/generics/wildcards.html