产生背景:在Java泛型中,用 T 作为类型参数,而由于Java泛型不是不同于数组具有 协变 特性,即Boy IS-A People但List NOT IS-A List,所以为了方便类型的转换…产生了extends以及super作为类型界定,其中extends作为上界,super作为下界。以下图的继承关系为例 < T extends B>: < T super B>:
1.T extends Comparable<? super T> 可以将 Comparable<? super T> 看作一个整体,也就是所,T需要继承(实现)Comparable接口。
2.Comparable<? super T>可以理解为Comparable的参数类型可以是T或者T的父类
3.结合起来理解,该类传入的参数需要实现了Comparable接口,而接口的参数必须是T或者T的父类(接口)。
4.基于 3 既然这样,为什么不直接使用<T extends Comparable< T >> 呢?
很简单,因为这样不是不能用,而是限制了传入参数的类型!只能做到传入的参数T实现了Comparable接口而且Comparable的参数为T,那要是Comparable的参数是别的呢?是参数T的父类或者子类呢?为了方便理解,这里举一个例子:
先定义继承体系的两个类
public class Boy extends People{ public Boy(Integer age) { super(age); } } public class People implements Comparable<People>{ private Integer age; public People(Integer age) { this.age = age; } @Override public int compareTo(People people) { return this.age-people.age; } }测试类
public class Test { //创建一个符合<T extends Comparable<T>>参数的方法 public static <T extends Comparable<T>> void one(List<T> t){ } //创建一个符合<T extends Comparable<? super T>>参数的方法 public static <T extends Comparable<? super T>> void two(List<T> t){ } public static void main(String[] args) { //构建list1 List<People> list1 = new ArrayList<>(); list1.add(new People(20)); list1.add(new Boy(12)); //构建list2 List<Boy> list2 = new ArrayList<>(); list2.add(new Boy(13)); list2.add(new Boy(14)); //符合预期,相当于<People extends Comparable<People>> Test.one(list1); //不符合预期,相当于<Boy extends Comparable<People>>,提示编译期错误 Test.one(list2); //符合预期,相当于<People extends Comparable<People super People>> Test.two(list1); //符合预期,相当于<Boy extends Comparable<Boy super People>> Test.two(list2); } }其中Test.one(list2)发生了编译期错误: 这里错误的原因是 Boy因为继承的缘故,间接地实现了Comparable< People>接口,与参数类型的<T extends Comparable< T>> —> <Boy extends Comparable< Boy>>不符合 。
看到这里大概就可以知道了,在某些特殊例子中,<T extends Comparable< T>>兼容性并不是很好,所以采用了<T extends Comparable< ? super T>>的形式,目的就是为了更好地兼容,很好地体现了泛型的特性。
参考 JDK源码 Collections类 链接: 如何理解 Java 中的 <T extends Comparable<? super T>>. 链接: 知乎.
