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

时间:2013-10-21 07:20:24

标签: java generics

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

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;
} 
如果省略Object绑定,

max似乎工作正常。

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;
}

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

1 个答案:

答案 0 :(得分:84)

两者具有相同的界限,但 是一个微妙的差异。

 <T extends Object & Comparable<? super T>> 

这会导致T在删除后成为Object

 <T extends Comparable<? super T>>

这会导致T在删除后成为Comparable


在这种情况下,它完成是因为.max早于Java 5.我们可以在this link中看到Joachim,请注意Java 1.4.2中.max的签名是:

public static Object max(Collection coll)

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

public static Comparable max(Collection coll)

哪会破坏API。我设法找到了this page讨论将旧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的签名。