通俗易懂,一分钟理解<T extends Comparable<? super T>>

<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个约束条件就容易理解了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值