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

sho*_*app 202 java generics

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

List<? extends HasWord> wordList = toke.tokenize();
Run Code Online (Sandbox Code Playgroud)

我并不担心代码的细节.令我困惑的是,通用表达式应该用英语表达的是什么.

谁可以给我解释一下这个?

Pow*_*ord 214

? extends HasWord
Run Code Online (Sandbox Code Playgroud)

表示"扩展的类/接口HasWord".换句话说,HasWord它本身或它的任何一个孩子......基本上任何可以使用instanceof HasWord加号的东西null.

在更多技术术语中,? extends HasWord是一个有界通配符,在第131页的Effective Java第3版第31项中有介绍.第2版的同一章可以在线获得PDF格式 ; 有界通配符上的部分是从第134页开始的第28项.

更新:PDF链接已更新,因为Oracle在一段时间后删除了它.它现在指向由伦敦玛丽女王大学电子工程和计算机科学学院主办的副本.

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

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

但是,如果所述签名是List<? extends HasWord>那么你可以通过List<ChildOfHasWord>代替.

请注意,List<? extends HasWord>和之间存在细微差别List<? super HasWord>.正如约书亚布洛赫所说:PECS =生产者延伸,消费者超级.

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

这听起来可能令人困惑.但是,你可以看到它Listsort命令(这仅仅是一个捷径Collections.sort的两ARG版本).而不是采取Comparator<T>,它实际上需要一个Comparator<? super T>.在这种情况下,比较器正在使用它的元素,List以便重新排序List本身.

  • "任何可以与instanceof一起使用的东西" - 加上空值.请记住,对于任何检查实例,null值都返回false. (17认同)
  • 不要忘记接口.的?不必代表一个班级! (12认同)
  • `List <HasWord>`正是你所描述的:一个包含任何对象`x`的列表,其中`x instanceof HasWord`返回true,'null`.你不需要通配符.通配符意味着它实际上也可以是另一种类型的列表,只要这种类型是`HasWord`的子类型.(对不起评论迟到了.) (9认同)

Jhe*_*ico 58

问号是"任何类型"的能指. ?孤独意味着

任何类型延伸Object(包括Object)

而你上面的例子意味着

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

  • 那么public Set &lt;Class &lt;?&gt;&gt; getClasses()是什么意思?与Set &lt;Class&gt;有什么区别?我正在看`javax.ws.rs.core.Application`。 (2认同)

lim*_*imc 14

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

public class A extends HasWord { .. }
public class B extends HasWord { .. }
public class C { .. }
public class D extends SomeOtherWord { .. }
Run Code Online (Sandbox Code Playgroud)

... wordList只能包含As或Bs的列表或两者的混合,因为这两个类都扩展了相同的父类或null(它的实例检查失败HasWorld).

  • 不仅是具体的,也是抽象的子类. (8认同)
  • 不仅是具体的和抽象的子类,还有子接口:`List <?extends Collection <String >> list = new ArrayList <List <String >>();`. (2认同)
  • 你不需要使用通配符,实际上:`List <HasWord>`对此也是如此.这里的要点是这个变量可以包含一个`List <A>`或`List <B>`以及一个`List <HasWord>`. (2认同)

Tom*_*ine 11

也许一个人为的"现实世界"的例子会有所帮助.

在工作中,我们有不同口味的垃圾箱.所有垃圾箱都含有垃圾,但有些垃圾箱是专家,不会带走所有类型的垃圾.所以我们有Bin<CupRubbish>Bin<RecylcableRubbish>.类型系统需要确保我不能将我HalfEatenSandwichRubbish放入这些类型中的任何一种,但它可以进入一个普通的垃圾桶``Bin Bin<Rubbish>Bin BinRubbish RubbishBin`.

(注意:Bin<? extends Rubbish>并不意味着只读.例如,我可以采取适当的预防措施从一个未知专业的垃圾箱中取出一块垃圾,然后将其放回另一个地方.)

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


jjn*_*guy 8

用英语:

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

一般来说?,泛型意味着任何类。并且extends SomeClass指定该对象必须扩展SomeClass(或成为该类)。