事情要从一次面试说起,面试官问了这么一个问题,在JDK下面这个方法中:
public static <T extends Comparable<? super T>> void sort(List<T> list)
这里面<T extends Comparable<? super T>>有什么用?
很明显,sort方法是要对一个List排序,这个List中的元素类型为T,<T extends Comparable<? super T>>是对T进行了约束,要求T必须是一个实现了Comparable接口的类型。那么为什么不是<T extends Comparable<T>>和<T extends Comparable<?>>呢?
如果写成了<T extends Comparable<?>>,那么T的类型就过于宽泛。下面这个类会被认为是合法的类型,但实际上这个类实现的comparable接口全无意义可言,一个类型怎么会和一个和它毫无关系的类型做比较呢?
public class Bar implements Comparable<String>
如果写成了<T extends Comparable<T>>,那么T的类型就过于严格。因为实际中有可能是T继承了类型S,S实现了Comparable<S>,这样T实际上是实现了Comparable<S>。那么对T类型排序的时候,可以借助于Comparable<S>的实现进行。
<T extends Comparable<? super T>>在一定程度上解决了以上两个问题,但也不是十全十美,比如下面这个类
public class Bar extends RuntimeException implements Comparable<Exception>
这个Comparable实现的也是莫名其妙,因为理论上x.compareTo(y)和y.compareTo(x)的符号应该相反才对,可是Exception根本没有compareTo方法。但是这个类也能通过sort方法的检查。
归根结底,还是Comparable这个接口的约束力太弱,理论上实现了Comparable接口的对象,只能和相同类型的对象进行比较。但是就像equals和hashcode的代码契约一样,现在编译器在语法层面完全无法提供检查,只能靠程序员的职业素养来产生良好的代码,真是太不开心了。