java泛型机制有一种奇葩的使用方式,示例代码如下
abstract class Animal<T extends Animal<T>>{
}
咋一看,一脸懵逼,仔细一看, 把自己绕了进去,这代码什么意思?
事实上这段代码要在具体的应用场景下才能搞清楚意义
我们来扩展一下刚才那个类,并实现两个类来继承他
abstract class Animal<T extends Animal<T>>{
private String name;
public Animal(String name) {
this.name = name;
}
abstract void mating(T t);
public String toString() {
return this.name;
}
}
class Dog extends Animal<Dog> {
public Dog(String name) {
super(name);
}
@Override
void mating(Dog dog) {
System.out.println(this + "和" + dog + "生小狗");
}
}
class Cat extends Animal<Cat> {
public Cat(String name) {
super(name);
}
@Override
void mating(Cat cat) {
System.out.println(this + "和" + cat + "生小猫");
}
}
Dog和Cat继承自 Animal,继承语法如下
class Dog extends Animal<Dog>
class Cat extends Animal<Cat>
然后我们再来匹配一下这个泛型模式
abstract class Animal<T extends Animal<T>>
是不是契合在一起了?
Dog extends Animal<Dog>
对应的不就是
<T extends Animal<T>>
嘛
这么做有什么好处呢?以上面的代码为例
Dog类和Cat实现了父类Animal的抽象方法mating
abstract void mating(T t);
这个方法的意思是交配,狗和猫都有交配能力,没毛病
有意思的是,狗显然只能和狗交配,猫只能和猫交配,如果按照传统继承模式,抽象方法的实现
abstract void mating(Animal t)
只能接受表示动物的父类,这显然有问题,如果我们调用Dog的mating方法,传入一个Animal 的实现Cat对象,那么程序将出现BUG,狗和猫显然不能交配,因为有生殖隔离。
而以这种方法实现,就可以避免这种问题,dog的mating只能接受Dog类型参数,cat也一样
Dog dog1 = new Dog("dog1");
Dog dog2 = new Dog("dog2");
Cat cat1 = new Cat("cat1");
Cat cat2 = new Cat("cat2");
dog1.mating(dog2);//通过编译
cat1.mating(cat2);//通过编译
dog1.mating(cat1);//编译出错
dog2.mating(cat2);//编译出错
这就可以避免掉某些时候运行期间类型判断,比如
void mating(Animal dog) {
if(dog instanceof Dog) {
System.out.println(this + "和" + dog + "生小狗");
} else {
System.out.println("参数传递错误");
}
}
类型安全检查在编译期间就完成了。
jdk系统库中,也有用到这种泛型特性,比如Enum类型,他的定义是这样的
public abstract class Enum<E extends Enum<E>>
对于枚举,我们通常这样定义
enum Animals{
Dog,Cat,Pig
}
实际上这只是一种语法糖,java编译器会将这个枚举编译成一个继承至Enum类的子类
Dog,Cat,Pig分别是Animals的实例,这些枚举对象上的某些方法比如compare只能接受Animals类型的;或者getDeclaringClass方法,返回Class<Animals>,而不是任何Enum类型的子类,这样能最直观方便的保证类型的安全性。
网友评论