prv*_*rvn 24 java generics collections comparable
为什么要Collections.sort(List<T>)
签名:
public static <T extends Comparable<? super T>> void sort(List<T> list)
Run Code Online (Sandbox Code Playgroud)
并不是 :
public static <T extends Comparable<T>> void sort(List<? extends T> list)
Run Code Online (Sandbox Code Playgroud)
Tag*_*eev 19
您提出的签名可能适用于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);
Run Code Online (Sandbox Code Playgroud)
它完全适用于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);
Run Code Online (Sandbox Code Playgroud)
这里T
应该推断为java.util.Date
.但是,Java 7规范不允许这样的推断.因此,此代码可以使用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
Run Code Online (Sandbox Code Playgroud)
Java-8中的类型推断得到了极大的改进.独立JLS 第18章现在是专门给它,而在Java-7规则是简单得多.
// 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)
Run Code Online (Sandbox Code Playgroud)
这些签名不同,因为它们会对类型之间的关系有不同的要求T
和类型参数Comparable
的定义T
.
假设你有这个类:
class A implements Comparable<Object> { ... }
Run Code Online (Sandbox Code Playgroud)
然后,如果你有
List<A> list = ... ;
sort0(list); // works
sort1(list); // fails
Run Code Online (Sandbox Code Playgroud)
sort1
失败的原因是没有类型T
可以与自身相比,也就是列表类型的超类型.
事实证明,类A
是畸形的,因为Comparable
需要满足某些要求的对象.特别是逆转比较应该反转结果的符号.我们可以的实例进行比较的A
一个Object
,但不是相反,所以这个要求被违反.但是请注意,这是一个需要语义的Comparable
,而不是由类型系统强加的.仅考虑类型系统,这两个sort
声明确实不同.