面向问题编程——Java泛型

Java中的泛型历来烧脑,从Object到上界下界修罗界,各种神奇的编译错误让泛型编程痛苦不堪。在这篇里,我总结一下泛型声明方式。

最原始的泛型方式——抄袭Object!

Java中,一切对象基于Object。所以,当没有泛型可用的远古时代,一切泛型,都通过Object来实现。首先让我们设计一个与相同类型的对象对比的接口。

// 使用Object作为基类完成泛型
interface Cmp_0 {
    int compareTo(Object o);
}

这样的方法确实极为简单。可是问题是显然的,参数o的类型无法保障,随时传进来一个鬼东西,触发异常。

简单泛型——TTT

为了解决上述的问题,不妨把C++的泛型语法借鉴过来,一个T简明易懂。

// 最简单的泛型方式
interface Cmp_1<T> {
    int compareTo(T o);
}

这样,我们就能解决比较对象不一致的问题了。可是这就解决了所有问题了吗?

类型限制+一致性——extends

参见下面的场景:我想声明一个只能储存Classed及其子类型的类Party,并且所有Classed类型的对象都是同一种子类型的。说人话就是:同一阶级的人组成党派。

一个自然地想法是使用Classed来声明成员变量。

class Party_0 {
    // 领袖
    private Classed leader;
    // getters, settters
}

然而这会滋生一个问题,比如一个无产阶级的党派可以设置资本家作为领袖,这种Naive的事情不能发生。而现在的泛型方式,虽然能够保证类型的一致,但是不能保证这个类型是Classed子类。

class Party_1<T> {
    // 领袖
    private T leader;
    // getters, setters
}

直接通过父类声明,可以解决继承的限制;通过泛型,可以解决类型的一致性问题。它们结合起来呢?

Java用extends关键字来的表明两个类的继承关系,这里Java讲这种关系延伸到了泛型之中。因为泛型类基于extends后面的类,所以称这种声明为上界。
针对刚才的问题,我们写如下的代码 :

// T必须是Classed或者其子类
class Party_2<T extends Classed> {
    private T leader;
}

通过描述T和Classed关系,保证了任何T都是Classed的子类,并且leader一定是类型T的,这样就解决了对类型限制和一致性的问题。

下界为子而生——super

然而只有上界还是不够的。让我们来看这样一个问题。

任何游戏都基于CF,而基于CF的游戏,他们的粉(nao)丝(can)喜欢撕逼。也就是说,它们是Sibiable的。

// 可撕逼的
interface Sibiable<T> {
    // 对啦,撕逼能有什么结果呢?笑了
    void sibi(T sb);
}

// 游戏起源CF
class Cf implements Sibiable<Cf> {
}

// DNF以F结尾,抄袭CF
class DNF extends Cf {
}

当然,能撕逼的不仅仅有游戏,还有动漫。任何动漫都是来源于《喜羊羊(HappyShit)》的,所有的动漫,也都可以撕逼。

// 动漫屎祖喜羊羊
class HappyShit implements Sibiable<HappyShit> {
}

// 黄段子当然也抄袭了喜羊羊
class YellowSegments extends HappyShit {
}

如果我们需要编写一个列表,来记录下所有可以撕逼的东西怎么办呢?利用刚才上界,我们可以写出这样的代码。

class SibiList_0<T extends HappyShit> {
}
class SibiList_1<T extends Cf> {
}

然而这并不满足我们的需求。我们脑洞大开一下,使用一个嵌套的约束呢?

class SibiList_2<T extends Sibiable<T>> {
}

我们很容易发现,这样做除了Cf、HappyShit两个基类外,他们任何的子类都不能添加进去!因为他们子类实现的是Sibiable<Cf>接口或者Sibiable<HappyShit>,而类的要求是必须要实现自身作为参数的Sibiable接口。

如果一个类Self实现了Sibiable<Self>,那么它的子类都实现了这个接口。Self这个类,与它的子类是超类与子类的关系,也就是super。那么将这种关系推广到泛型之中不就好了嘛?于是我们有了这样的代码:

class SibiList_3<T extends Sibiable<? super T>> {
}

这里的?就是对一个泛型的使用。从内向外理解一下就是:
首先要一个类它是T的超类,这个类作为Sibiable的参数类型。而T是这个Sibiable的子类。说人话就是:T的父类实现了Sibiable<自身>的接口。

总结

Java的泛型机制从最原始的Object到最终的上下界限制,不断优化迭代,使用更复杂的语法,使之更符合需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值