Collections.sort() 声明:为什么 <?超级 T> 而不是 <T>

Collections.sort() declaration: why <? super T> rather than <T>

为什么 Collections.sort(List<T>) 有签名:

public static <T extends Comparable<? super T>> void sort(List<T> list) 

而不是:

public static <T extends Comparable<T>> void sort(List<? extends T> list)

它们的不同之处在于 ? super TT 的限制更少。这是一个 Lower Bounded Wildcard(链接的 Java 教程部分说)

The term List<Integer> is more restrictive than List<? super Integer> because the former matches a list of type Integer only, whereas the latter matches a list of any type that is a supertype of Integer.

Integer替换为T,这意味着一个T 一个java.lang.Object.

您提议的签名可能适用于 Java-8。然而,在之前的 Java 版本中,类型推断并不是那么聪明。假设您有 List<java.sql.Date>。请注意,java.sql.Date 扩展了 java.util.Date,它实现了 Comparable<java.util.Date>。当你编译

List<java.sql.Date> list = new ArrayList<>();
Collections.sort(list);

它在 Java-7 中完美运行。这里 T 被推断为 java.sql.Date 实际上是 Comparable<java.util.Date>Comparable<? super java.sql.Date>。但是让我们试试你的签名:

public static <T extends Comparable<T>> void sort(List<? extends T> list) {}

List<java.sql.Date> list = new ArrayList<>();
sort(list);

这里T应该推断为java.util.Date。然而 Java7 规范不允许这样的推断。因此这段代码可以用 Java-8 编译,但在 Java-7:

下编译时失败
Main.java:14: error: method sort in class Main cannot be applied to given types;
        sort(list);
        ^
  required: List<? extends T>
  found: List<Date>
  reason: inferred type does not conform to declared bound(s)
    inferred: Date
    bound(s): Comparable<Date>
  where T is a type-variable:
    T extends Comparable<T> declared in method <T>sort(List<? extends T>)
1 error

类型推断在 Java-8 中得到了极大改进。分离JLSchapter 18 is dedicated to it now, while in Java-7 the rules were简单多了。

// 0
public static <T extends Comparable<? super T>> void sort0(List<T> list) 

// 1
public static <T extends Comparable<T>> void sort1(List<? extends T> list)

这些签名不同是因为它们对 T 类型和 Comparable 的类型参数之间的关系提出了不同的要求 T.

假设你有这个 class:

class A implements Comparable<Object> { ... }

那么如果你有

List<A> list = ... ;
sort0(list); // works
sort1(list); // fails

sort1 失败的原因是 没有 类型 T 可以与自身相比较,或者是超类型,列表的类型。

事实证明 class A 格式不正确,因为 Comparable 的对象需要满足某些要求。特别是反转比较应该反转结果的符号。我们可以将 A 的实例与 Object 的实例进行比较,但反之则不行,因此违反了此​​要求。但请注意,这是 Comparable 语义 的要求,而不是类型系统强加的。仅考虑类型系统,两个 sort 声明确实不同。