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


73

刚刚经历了Java 7java.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;
} 

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

实际上在任何情况下界限都会有所作为吗?如果是,请提供一个具体示例。


4
<T扩展对象和E>与<T扩展E>的重复,尽管这篇文章有更好的问答。
Paul Bellora

Answers:


87

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

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

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

 <T extends Comparable<? super T>>

这将导致T成为Comparable下擦除。


在这种情况下,这样做是因为.maxJava 5早于Java5。我们可以在此链接中看到Joachim,条件是.maxJava 1.4.2中的签名是:

public static Object max(Collection coll)

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

public static Comparable max(Collection coll)

这会破坏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的签名。


是否有理由这样做是合乎需要的?
templatetypedef

可能是因为Collection.maxJava 5早于Generics而已。并且由于返回值就是T擦除后将更改方法签名的值。
约阿希姆·绍尔

@templatetypedef是的,主要是旧代码。由于Java并不总是具有在擦除后具有方法签名的泛型,因此与泛型之前的签名保持相同是可取的。我记得在docs.oracle.com上阅读过有关它的信息-它需要我多一点时间才能找到它。
本杰明·格林鲍姆

我从没想过类型擦除后的泛型签名。
Shashank
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.