这是从斯坦福解析器附带的一些示例中截取的一小段代码。我已经用Java开发了大约4年,但从来没有非常清楚这种风格的代码应该表示什么。
List<? extends HasWord> wordList = toke.tokenize();
我不担心代码的细节。我困惑的是,在英语中,这种通用表达到底应该表达什么。
有人能给我解释一下吗?
这是从斯坦福解析器附带的一些示例中截取的一小段代码。我已经用Java开发了大约4年,但从来没有非常清楚这种风格的代码应该表示什么。
List<? extends HasWord> wordList = toke.tokenize();
我不担心代码的细节。我困惑的是,在英语中,这种通用表达到底应该表达什么。
有人能给我解释一下吗?
当前回答
列表< ?>接受任何扩展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检查中失败)。
其他回答
? extends HasWord
意思是“扩展HasWord的类/接口”。换句话说,HasWord本身或它的任何子…基本上任何可以使用instanceof HasWord + null的东西。
用更专业的术语来说,?HasWord是一个有界通配符,在Effective Java 3rd Edition的第31项中介绍,从第139页开始。第二版中的同一章节在网上以PDF格式提供;关于有界通配符的部分是第134页开始的第28项。
更新:PDF链接已经更新,因为Oracle之前删除了它。它现在指向了伦敦玛丽女王大学电子工程和计算机科学学院的副本。
更新2:让我们更详细地了解为什么要使用通配符。
如果你声明一个方法,它的签名希望你传入List<HasWord>,那么你唯一能传入的就是List<HasWord>。
然而,如果所说的签名是List<?extends HasWord>,那么你可以传入List<ChildOfHasWord>代替。
注意,List<?扩展HasWord>和List<?超级HasWord >。正如约书亚·布洛赫所说:PECS =生产者延伸,消费者超。
这意味着,如果你传入一个你的方法从中提取数据的集合(也就是说,这个集合产生元素供你的方法使用),你应该使用extends。如果你传入一个集合,你的方法将数据添加到其中(即集合正在消耗你的方法创建的元素),它应该使用super。
这听起来可能令人困惑。但是,您可以在List的sort命令中看到它(这只是Collections.sort的双参数版本的快捷方式)。它没有取Comparator<T>,而是取Comparator<?超级T >。在这种情况下,Comparator正在消耗List的元素,以便对List本身进行重新排序。
问号表示“任何类型”。? 就意味着
任何类型的扩展对象(包括对象)
而你上面的例子意味着
任何类型的扩展或实现 HasWord(包括HasWord if HasWord是非抽象类)
英文:
它是某种类型的列表,扩展了类HasWord,包括HasWord
一般来说?在泛型中是指任何类。而extends SomeClass则指定该对象必须扩展SomeClass(或者是该类)。
列表< ?>接受任何扩展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检查中失败)。
问号用于定义通配符。签出关于它们的Oracle文档:http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html