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

刚刚浏览了 Java7的 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;
}

实际上是否有任何情况下界限会产生影响? 如果是,请提供一个具体的例子。

2123 次浏览

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

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

这将导致 T变成一个被擦除的 Object

 <T extends Comparable<? super T>>

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


在这种情况下,这样做是因为 .max早于 Java5。我们可以在 这个链接 Joachim 中看到,只要 Java 1.4.2中 .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 Comparable max(Collection coll),这是不同于最大() : public static Object max(Collection coll)的原始签名

人们当然可以为 max ()指定这个签名,但是没有这样做,而且所有调用 Collections.max ()的旧二进制类文件都依赖于返回 Object 的签名。