在研究Java的Collection类(OpenJDK 8_update40)之后,我发现了以下方法:
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
Iterator<? extends T> i = coll.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;
}
我不完全理解这里使用泛型类型。据我所知,T是Object的子类型,它也必须实现Comparable接口,该接口也通过泛型参数进行参数化。 Comparable状态的参数必须是T的某种超类型。由于我们有某种递归类型定义。
但这是我的问题:据我所知,Java中的每个类型都是Object的子类型,那么他们为什么要指定 它在T?
的定义范围内答案 0 :(得分:6)
这是出于向后兼容的原因。
使用泛型类型时,此泛型类型具有下限,例如:
<T extends Foo & Bar> void someMethod(T xxx)
然后someMethod
的运行时签名将是:
void someMethod(Foo xxx)
(好吧,好的,参数名称不存在,但是你得到了图片)。
现在,Collections.max()
在 JDK 5之前定义了;它的签名是:
public static Object max(Collection coll)
,在Java 5中,可以翻译为:
public static Object max(Collection<Object> coll)
问题是max
的返回值不能是Comparable
......
当然,在这种情况下,会增加更多困难:
Comparable
是PECS方式的“消费者”(因此Comparable<? super T>
); Collection
可以是T
或任何扩展T
的任何类型,因此? extends T
;我们不关心实际类型,只保证Collection
保证返回至少 T的内容。这解释了有点复杂的签名......
答案 1 :(得分:0)
因为如果你不使用&#34; T&#34;该集合只接受Object的实例。
例如,String是Object的子类型,但不会编译,因为集合只接受Object实例。
答案 2 :(得分:0)
这是由于covariance vs. contravariance。
作为一般规则:
<? extends T>
<? super T>