Answers:
? extends HasWord
表示“扩展的类/接口HasWord
”。换句话说,HasWord
它本身或其任何子代...基本上可以与instanceof HasWord
plus 一起使用的任何东西null
。
用更多的技术术语来说,? extends HasWord
是有界通配符,在139页有效的Java 3rd Edition的第31条中进行了介绍。有界通配符的部分是从第134页开始的第28项。
更新:由于Oracle不久前将其删除,因此PDF链接已更新。现在,它指向由伦敦玛丽皇后大学电子工程与计算机科学学院托管的副本。
更新2:让我们更详细地说明为什么要使用通配符。
如果声明一个方法的签名希望您传入List<HasWord>
,则唯一可以传入的是List<HasWord>
。
但是,如果所说的签名是,List<? extends HasWord>
那么您可以传递一个List<ChildOfHasWord>
。
请注意,List<? extends HasWord>
和之间有细微的差别List<? super HasWord>
。正如Joshua Bloch所说:PECS =生产者扩展,消费者超级。
这意味着,如果传入的是您的方法从中提取数据的集合(即,该集合正在生成供您的方法使用的元素),则应使用extends
。如果您传入的是方法要向其中添加数据的集合(即该集合正在消耗您的方法创建的元素),则应使用super
。
这听起来可能令人困惑。但是,您可以在List
的sort
命令中看到它(这只是Collections.sort的两个参数版本的快捷方式)。而不是取一个Comparator<T>
,实际上需要一个Comparator<? super T>
。在这种情况下,比较器将使用的元素,List
以便对列表本身进行重新排序。
List<HasWord>
正是您所描述的:一个包含任何对象的列表,这些对象x
为其x instanceof HasWord
返回true,以及null
。您不需要通配符。通配符意味着它实际上也可以是其他类型的列表,只要该类型是的子类型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或B或两者的混合物的列表,因为这两个类都扩展了相同的父项或null
(这会导致instanceof检查失败HasWorld
)。
List<? extends Collection<String>> list = new ArrayList<List<String>>();
。
List<HasWord>
这样做也是如此。这里的关键是,这个变量可以包含一个List<A>
或List<B>
以及一个List<HasWord>
。
人为的“现实世界”示例可能会有所帮助。
在我的工作场所,我们有各种口味的垃圾桶。所有垃圾箱都包含垃圾,但是有些垃圾箱是专业垃圾箱,不会吸收所有类型的垃圾。所以我们有Bin<CupRubbish>
和Bin<RecylcableRubbish>
。类型系统需要确保我不能放入HalfEatenSandwichRubbish
这两种类型中的任何一种,但是可以将其放入普通的垃圾箱中Bin<Rubbish>
。如果我想谈Bin
的Rubbish
可以专业,所以我不能把不兼容的垃圾,那么这将是Bin<? extends Rubbish>
。
(注意:? extends
这并不意味着是只读的。例如,我可以采取适当的预防措施,从一个未知专业的垃圾箱中取出一块垃圾,然后将其放回其他地方。)
不确定有什么帮助。存在多态性的指针对指针并不完全明显。
用英语讲:
它
List
是扩展类的某种类型HasWord
,包括HasWord
通常?
,泛型表示任何类。并且extends SomeClass
指定该对象必须扩展SomeClass
(或属于该类)。
问号用于定义通配符。查看有关它们的Oracle文档:http : //docs.oracle.com/javase/tutorial/java/generics/wildcards.html