这是从斯坦福分析器附带的一些示例中获取的一小段代码。我已经用Java开发了大约4年,但是从来没有对这种代码风格应该表明什么有非常深刻的理解。
List<? extends HasWord> wordList = toke.tokenize();
我并不担心代码的细节。令我困惑的是,通用表达式应该用英语传达的是什么。
有人可以向我解释一下吗?
答案 0 :(得分:203)
? extends HasWord
表示“扩展HasWord
的类/接口。”换句话说,HasWord
本身或其任何子女......基本上任何适用于instanceof HasWord
加null
的内容。
在更多技术术语中,? extends HasWord
是一个有界通配符,涵盖在Effective Java 3rd Edition的第31项中,从第139页开始。第2版的同一章是available online as a PDF;有界通配符上的部分是从第134页开始的第28项。
更新:PDF链接已更新,因为Oracle暂时删除了它。它现在指向由伦敦玛丽女王大学电子工程和计算机科学学院主办的副本。
更新2:让我们详细了解你为什么要使用通配符。
如果您声明一个其签名希望您传入List<HasWord>
的方法,那么您唯一能传入的内容就是List<HasWord>
。
但是,如果所述签名为List<? extends HasWord>
,那么您可以传入List<ChildOfHasWord>
。
请注意,List<? extends HasWord>
和List<? super HasWord>
之间存在细微差别。正如约书亚布洛赫所说:PECS =生产者延伸,消费者超级。
这意味着如果您传入一个集合,您的方法将数据从中拉出(即集合正在为您的方法生成元素),您应该使用extends
。如果您传入的是您的方法向其添加数据的集合(即集合正在消耗您的方法创建的元素),则应使用super
。
这听起来可能令人困惑。但是,您可以在List
的{{3}}命令中看到它(这只是Collections.sort的两个arg版本的快捷方式)。它实际上需要Comparator<T>
,而不是Comparator<? super T>
。在这种情况下,比较器使用List
的元素来重新排序列表本身。
答案 1 :(得分:54)
问号是“任何类型”的能指。仅?
就意味着
任何展开
Object
的类型(包括Object
)
虽然上面的示例意味着
任何类型的扩展或实施
HasWord
(包括HasWord
ifHasWord
是一个非抽象类)
答案 2 :(得分:12)
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的列表或两者的混合,因为这两个类都扩展了相同的父级或null
(对HasWorld
的实例检查失败)。
答案 3 :(得分:9)
也许一个人为的“现实世界”的例子会有所帮助。
在工作中我们有不同口味的垃圾箱。所有垃圾箱都含有垃圾,但有些垃圾箱是专家,不会带走所有类型的垃圾。我们有Bin<CupRubbish>
和Bin<RecylcableRubbsih>
。类型系统需要确保我不能将HalfEatenSandwichRubbish
放入这些类型中的任何一种,但它可以进入一般的垃圾箱``Bin . If I wanted to talk about a
Bin of
垃圾{{ 1}} Bin`。
(注意:which may be a specialist so I can't put in incompatible rubbish, then that would be
并不意味着只读。例如,我可以采取适当的预防措施从一个未知专业的垃圾箱中取出一块垃圾,然后将其放回另一个地方。)< / p>
不确定这有多大帮助。存在多态性的指针指针并不完全明显。
答案 4 :(得分:4)
英文:
某种类型的
List
扩展了类HasWord
,包括HasWord
一般来说,泛型中的?
表示任何类。 extends SomeClass
指定该对象必须扩展SomeClass
(或者是该类)。
答案 5 :(得分:1)
问号用于定义通配符。查看有关它们的Oracle文档:http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html