Java 泛型的类型参数中的问号是什么意思?

2022-08-31 05:35:05

这是一小段代码,取自斯坦福解析器附带的一些示例。我已经在Java中开发了大约4年,但从未对这种代码风格应该表示什么有很强的理解。

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

我不担心代码的细节。我感到困惑的是,通用表达式究竟应该用英语传达什么。

有人可以向我解释一下吗?


答案 1
? extends HasWord

表示“扩展的类/接口”。换句话说,它自己或它的任何一个孩子...基本上任何可以与加号一起使用的东西。HasWordHasWordinstanceof HasWordnull

用更专业的术语来说,是一个有界通配符,在 Effective Java 3rd Edition 的第 31 项中介绍,从第 139 页开始。第2版的同一章节以PDF格式在线提供;有界通配符上的部分是从第 134 页开始的第 28 项。? extends HasWord

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

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

如果您声明一个方法,其签名希望您传入 ,那么您唯一可以传入的就是 .List<HasWord>List<HasWord>

但是,如果所述签名是,那么您可以改为传递。List<? extends HasWord>List<ChildOfHasWord>

请注意,和 之间存在细微的区别。正如Joshua Bloch所说:PECS =生产者扩展,消费者超级。List<? extends HasWord>List<? super HasWord>

这意味着,如果要传入一个集合,而您的方法从中提取数据(即该集合正在生成供方法使用的元素),则应使用 。如果要传入方法向其添加数据的集合(即,该集合正在使用方法创建的元素),则应使用 。extendssuper

这听起来可能令人困惑。但是,您可以在 的 sort 命令中看到它(这只是 Collections.sort 的双 arg 版本的快捷方式)。它实际上需要一个 .c 而不是取 一个 。在这种情况下,比较器正在消耗 的元素,以便对列表本身进行重新排序。ListComparator<T>Comparator<? super T>List


答案 2

问号是“任何类型”的能指。 单独意味着?

任何类型扩展(包括ObjectObject)

而您上面的例子意味着

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


推荐