<T extends Comparable<? super T>>是Java中常用的范式,查了一些资料,感觉说的都比较理论化,不够通俗易懂,这里写一下个人的理解,抛砖引玉。
1.应用场景
首先这个范式用在哪里,它的应用场景是什么呢?
有这么一个场景:在淘宝首页vlayout框架中,有一个类Range,这个类的作用是,在被管理的一大堆布局对象中,根据判断条件,找到符合条件的那1个布局对象。这个类的定义就用到了<T extends Comparable<? super T>>,部分代码如下图所示。所以,这个范式的应用场景,简单地说,可以用来在许多对象中找到符合条件的那个。
public final class Range<T extends Comparable<? super T>> {
public Range(@NonNull final T lower, @NonNull final T upper) {
if (lower == null)
throw new IllegalArgumentException("lower must not be null");
if (upper == null)
throw new IllegalArgumentException("upper must not be null");
mLower = lower;
mUpper = upper;
if (lower.compareTo(upper) > 0) {
throw new IllegalArgumentException("lower must be less than or equal to upper");
}
}
....
....
其他代码略
}
2.对模板T的限制条件
上述<T extends Comparable<? super T>>范式代码中,实际上是对模板 T 进行了条件限制,只有满足条件,才可以放到Range类里面进行使用。这两个条件就是:
(1)模板必须实现了Comparable<T> 接口,自己实现的或者是父类(超类)实现的都行;
(2)在实现Comparable接口的方法compareTo中,输入参数必须是同级类或者是自己的父类(超类);
满足了这两个条件,就可以定义并进行使用,以类Person为例,则有
Range<Person> personRange = new Range<Person>();
3.为什么要有这两个限制条件
那么为什么必须要有这两个限定条件呢?
第1个限定条件好理解,因为要从一堆对象里找到符合条件的那1个,必须要对对象进行比较,Java中不支持运算符重载,因此只能通过实现 Comparable<T> 比较接口来比较两个对象。
第2个条件,为什么要说明compareTo方法输入参数是父类或超类呢?可以这样理解:
比如还是Person类,类代码如下。由于对象的比较一般都是和同类比较(也可以和其他类比较,根据实际情况来),因此在Comparable<Person>接口中传入的比较参数是Person。
class Person implements Comparable<Person>{
protected String name;
protected int age;
public Person(String name,int age){
this.name=name;
this.age=age;
}
@Override
public int compareTo(Person person) {
return this.age == person.age? 0 : this.age-person.age;
}
}
Person的子类Teacher和孙类MathTeacher,代码如下。Teacher类和MathTeacher类都继承了Person的Comparable接口,就是说:调用compareTo方法的输入参数是“Person”,正是Teacher类和MathTeacher类的超类。
//老师类
class Teacher extends Person{
protected String job="老师";
public Teacher(String name,int age){
super(name,age);
}
}
//数学老师类
class MathTeacher extends Teacher {
protected String subject="数学";
public MathTeacher(String name,int age){
super(name,age);
}
}
放到Range定义中进行理解:
- 当要定义Range<Teacher>时,Range<T extends Comparable<? super T>>的实际情况就是Range<Teacher extends Comparable<Person>>,此时Person是Teacher的父类,正是对应于<? super Teacher>,此时的模板T是Teacher;
- 若是Range<MathTeacher>,则对应于Range<MathTeacher extends Comparable<Person>>,此时,Person是MathTeacher父类的父类,对应于<? super MathTeacher>,此时的模板T是MathTeacher;
可以看出,范式中使用<? super T>,与Range<Teacher> 和Range<MathTeacher>的使用情况刚好吻合,因为Person正是两个类的超类。
加入<? super T>的目的,可以理解为当Person代入模板能够正常使用时,它的子类及后代类也都同样可以正常使用。所以,第2个约束条件就容易理解了。