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

2022-08-31 13:31:36

刚刚浏览了Java 7类的实现,看到了一些我不明白的东西。在函数签名中,为什么受 ?java.util.CollectionsmaxTObject

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如果省略对象绑定,似乎工作正常。

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

这将导致擦除不足。TObject

 <T extends Comparable<? super T>>

这将导致擦除不足。TComparable


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

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)这很好,除了此签名的擦除是:这与 max() 的原始签名不同:public static Comparable max(Collection coll)public static Object max(Collection coll)

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


答案 2

推荐