java基础_泛型自限定应该怎么理解?

SelfBounded的神秘

在《Java编程思想》中关于泛型的讲解中,提到了自限定类型:

class SelfBounded<T extends SelfBounded<T>>{}

作者对其的定义是 “我在创建一个新类,它继承自一个泛型类型,这个泛型类型接收自己的类名作为参数”。

是不是一头雾水?鉴于《Java编程思想》的理解层次和深度,相信大多数读者都不能一窥其究竟。JAVA为什么要有这个东西?它解决了啥问题?等等诸如此类的。

下面我会基于我自己的理解,采用一步一步递进的讲解方式。来说明这个问题,当然基于笔者知识水平的限制,如果有理解错误和含糊不清的地方,希望大家不吝指教。

到底什么是自限定?

在某些场景之下,我们需要编写一个类(基类),在这个基类中编写若干方法,这些方法的参数或者是返回值都要求是这个类本身;而且当有子类继承这个基类之后,这些方法的参数或者是返回值都要随着子类的变化而变化。

现在通过上面的描述,我们大概理解了什么是自限定;我们可以发现,自限定是站在继承的场景之下来讨论问题的。

然后我们通过最原始的方式来实现这个需求:

public class GenericDemo013 {

    public static void main(String[] args) {
        Derived base = new Derived();
        base.set(new Derived());
        System.out.println(base.get().getClass().getSimpleName());
    }
}

class Base{
    Base t;
    public void set(Base t){
        this.t = t;
    }
    public Base get(){
        return t;
    }
}
class Derived extends Base{
    Derived t;
    //重载了set(子类的set还存在)
    public void set(Derived t){
        this.t = t;
    }
   //重写了get(子类的get不存在)
    public Derived get(){
         return t;
    }
}

从表面上看,我们似乎采用上面的方式完美的解决了这个需求。稍加思索就会发现这种写法完全无法体现"继承"的优势,而且代码量也似乎比较臃肿。

下面来看一种比较优雅的实现方法:

package com.java.basic.generic;


public class GenericDemo013 {

    public static void main(String[] args) {
        Derived base = new Derived();
        base.set(new Derived());
        //输出是Derived
        System.out.println(base.get().getClass().getSimpleName());

    }
}

class Base<T>{
    T t;
    public void set(T t){
        this.t = t;
    }
    public T get(){
        return t;
    }
}
class Derived extends Base<Derived>{ }


哇,相当nice。这里充分使用到了继承的优势。且在子类中不用重写任何方法;可以说是相当完美了。但是我们要知道的是,Base类没有做任何限制,所以它也可以这样继承:

class Derived extends Base<String>{ }

很明显,这样的话,set(T t) 和 T get() 方法中的T就变成了String,而不是子类本身。这违背了自限定的原则。

正真的自限定:

package com.java.basic.generic;


public class GenericDemo013 {

    public static void main(String[] args) {
        Derived base = new Derived();
        base.set(new Derived());
        //输出是Derived
        System.out.println(base.get().getClass().getSimpleName());

    }
}

class Base<T extends Base<T>>{
    T t;
    public void set(T t){
        this.t = t;
    }
    public T get(){
        return t;
    }
}
class Derived extends Base<Derived>{ }
class Derived1 extends Base<String>{ } //编译错误


OK,这里不在过多解释,一个简单的限定而已。

自限定(SelfBounded)的价值

综上所述,我们可以看到自限定类型的价值在于可以产生协变参数类型——方法参数类型会随着子类的变化而变化。

参考

<<java编程思想(第四版)>>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值