为什么T在Collections.max()签名中受Object限制?

Max*_*lov 69 java generics

刚刚完成了Java 7的java.util.Collections类的实现,看到了一些我不理解的东西.在max函数签名中,为什么T受限于Object

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;
} 
Run Code Online (Sandbox Code Playgroud)

max 如果省略Object绑定似乎工作正常.

public static <T extends 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;
}
Run Code Online (Sandbox Code Playgroud)

实际上是否存在绑定产生影响的任何情况?如果是,请提供一个具体的例子.

Ben*_*aum 84

这两个具有相同的边界,但有一个微妙的差异.

 <T extends Object & Comparable<? super T>> 
Run Code Online (Sandbox Code Playgroud)

这将导致T成为Object下删除.

 <T extends Comparable<? super T>>
Run Code Online (Sandbox Code Playgroud)

这将导致TComparable删除.


在这种情况下,它完成是因为.max早于Java 5.我们可以在这个链接中看到,Joachim慷慨地提供了.maxJava 1.4.2 中的签名:

public static Object max(Collection coll)
Run Code Online (Sandbox Code Playgroud)

如果我们用作<T extends Comparable<? super T>>约束,我们的签名就是

public static Comparable max(Collection coll)
Run Code Online (Sandbox Code Playgroud)

这会破坏API.我已经设法找到这个讨论将旧API转换为通用API的页面,它给出.max了一个具体的例子.

在这里他们解释了为什么这样max定义:

您还需要确保修订后的API保留与旧客户端的二进制兼容性.这意味着API的擦除必须与原始的,未经过授权的API相同.在大多数情况下,这自然会失败,但有一些微妙的情况.我们将研究一下我们遇到过的最微妙的案例,即方法Collections.max().正如我们在"使用通配符更多乐趣"一节中所看到的,一个合理的签名max()是:

public static <T extends Comparable<? super T>> T max(Collection<T> coll)这很好,除了这个签名的擦除是:public static Comparable max(Collection coll)它与max()的原始签名不同:public static Object max(Collection coll)

当然可以为max()指定此签名,但是没有完成,并且调用Collections.max()的所有旧二进制类文件都依赖于返回Object的签名.