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

Why is T bounded by Object in the Collections.max() signature?

刚刚完成了Java 7的EDCOX1,0类的实现,看到了一些我不理解的东西。在max函数签名中,为什么TObject的约束?

1
2
3
4
5
6
7
8
9
10
11
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似乎工作正常。

1
2
3
4
5
6
7
8
9
10
11
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
 <T extends Object & Comparable<? super T>>

这将导致T在擦除下成为Object

1
 <T extends Comparable<? super T>>

这将导致T在擦除时变成Comparable

在这种情况下,这是因为EDCOX1×4比Java 5早。我们可以看到,在这个链接中,约阿希姆善意地提供了在Java1.4.2中EDOCX1×4的签名是:

1
public static Object max(Collection coll)

如果我们使用>作为约束,我们的签名将是

1
public static Comparable max(Collection coll)

这会破坏API。我设法找到了这个讨论将旧的API转换为通用API的页面,它给出了.max作为一个特定的示例。

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

You also need to ensure that the revised API retains binary compatibility with old clients. This implies that the erasure of the API must be the same as the original, ungenerified API. In most cases, this falls out naturally, but there are some subtle cases. We'll examine one of the subtlest cases we've encountered, the method Collections.max(). As we saw in section More Fun with Wildcards, a plausible signature for max() is:

public static > T max(Collection coll) This is fine, except that the erasure of this signature is: public static Comparable max(Collection coll) which is different than the original signature of max(): public static Object max(Collection coll)

One could certainly have specified this signature for max(), but it was not done, and all the old binary class files that call Collections.max() depend on a signature that returns Object.