Java泛型中的问号是什么'类型参数mean?

这是从斯坦福解析器附带的一些示例中截取的一小段代码。我已经用Java开发了大约4年,但从来没有非常清楚这种风格的代码应该表示什么。

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

我不担心代码的细节。我困惑的是,在英语中,这种通用表达到底应该表达什么。

有人能给我解释一下吗?

135886 次浏览
? extends HasWord

意思是“扩展HasWord的类/接口。”换句话说,HasWord本身或它的任何子代…基本上任何可以与instanceof HasWord + null一起工作的东西。

在更专业的术语中,? extends HasWord是一个有界通配符,在Effective Java第三版的第31项中覆盖,从139页开始。第二版的同一章是可在网上以PDF格式下载;关于有界通配符的部分是第134页开始的第28项。

更新:PDF链接已经更新,因为Oracle之前删除了它。它现在指向了伦敦玛丽女王大学电子工程和计算机科学学院的副本。

更新2:让我们更详细地了解为什么要使用通配符。

如果你声明一个方法,它的签名希望你传入List<HasWord>,那么你唯一能传入的就是List<HasWord>

然而,如果所说的签名是List<? extends HasWord>,那么你可以传入一个List<ChildOfHasWord>

注意,在List<? extends HasWord>List<? super HasWord>之间有一个微妙的区别。正如约书亚·布洛赫所说:PECS =生产者延伸,消费者超。

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

这听起来可能令人困惑。然而,你可以在Listsort命令中看到它(这只是Collections.sort的双参数版本的快捷方式)。它不是取Comparator<T>,而是取Comparator<? super T>。在这种情况下,Comparator正在使用List的元素以重新排序List本身。

问号表示“任何类型”。?单独表示

任何扩展Object的类型(包括Object)

而你上面的例子意味着

任何类型的扩展或实现 HasWord(包括HasWord if HasWord是一个非抽象类)

英文:

它是某种类型的List,扩展了类HasWord,包括HasWord

一般来说,泛型中的?表示任何类。并且extends SomeClass指定该对象必须扩展SomeClass(或者是该类)。

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

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

... wordList只能包含a或b的列表,或者两者的混合,因为这两个类都扩展了相同的父类或null(这在HasWorld的instanceof检查中失败)。

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

在我工作的地方,我们有不同口味的垃圾桶。所有的垃圾桶都有垃圾,但有些垃圾桶是专门的,不收所有类型的垃圾。所以我们有Bin<CupRubbish>Bin<RecylcableRubbish>。类型系统需要确保我不能将我的HalfEatenSandwichRubbish放入这两种类型中的任何一种,但它可以放入一般的垃圾桶Bin<Rubbish>。如果我想讨论RubbishBin,它可能是专门的,所以我不能放入不兼容的垃圾,那么它将是Bin<? extends Rubbish>

(注:? extends并不表示只读。例如,在适当的预防措施下,我可以从一个不知名的特产垃圾桶里拿出一块垃圾,然后把它放回另一个地方。

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

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