深入理解Java GenericType

在Java的早期,类成员或方法使用的类型一般是固定的,这种情况往往是程序变得僵硬起来,要想为其他的类型实现相同的功能那么就要重新写一份,当然你也可以使用多态的机制让你的代码更加灵活,可是多态毕竟也是有限制的。例如早期的容器的设计,采用了Object的方式来保存所有类型的对象,如果想要从容器中取出你先前放进去的类型的对象,除了强转,也没有什么别的方法了,而且强转还会带来很多问题,因为你向这个Object的容器放入对象的时候并没有限制,所以ClassCastException问题就会伴随着你的程序。

Java5后引入了泛型,这将使得所有基于固定类型的代码将可以被得到复用,最典型的便是容器,现在你向创建一个装Integer的容器,它会强迫你只能添加Integer的数据,如果你试图添加一个String对象,那么你会得到一个编译时错误。

Java中的泛型真的那么好用吗?

貌似我们在使用泛型的时候感受到了它的便利,但有的时候我们想当然的认为泛型可以帮助我们解决下列问题:

class GenericType {
    void doSomething() {
        //omit
    }
}

public class GenericTypeTest<T> {

    public GenericTypeTest(T t) {
        t.doSomething();  //编译时错误
    }

    public static void main(String[] args) throws Exception{
        new GenericTypeTest(new GenericType());
    }
}

究竟发生了什么呢?

说到这里就不得不说一下Java中的泛型处理机制。和很多语言不同(如C++、Pythong)在使用泛型的时候会去检查该泛型对应的具体类型的是否存在着你使用的该方法,如果没有该方法,那么编译器会报错。而Java则做不到,泛型只存在于编译时的静态检查间,检查完成所有的泛型在没有边界的情况下将被擦除为Object类型,也可以通过类似<? extends Comparable>这种方法来指定边界,指定之后会被擦除为Comparable。所以JVM并不知道该对象具有doSomething()的方法,所以会报错。

解决以上问题:

给泛型T指定边界

public class GenericTypeTest<? extends GenericType> {

    public GenericTypeTest(T t) {
        t.doSomething();  //编译时错误
    }

    public static void main(String[] args) throws Exception{
        new GenericTypeTest(new GenericType());
    }
}

既然Java采用了擦除这种方式来实现泛型,那么他是怎样通过泛型获取真实类型的呢。实际上在擦除之前,编译器就已经在泛型的前面加入了强制转换。

总结:

之所以Java会以擦除方式来实现泛型,是因为Java的遗留问题,Java泛型是后来才加入进来的,为了支持更低版本的Java代码,就必须这样做,试想以下代码

//Java5后
List<T> list = new ArrayList<T>();
//Java5以前
List list = new ArrayList();

如果不使用擦除手段,那么这两个list将不会是一样的。但事实情况下却是:

public static void main(String[] args) throws Exception{
    List<String> list = new ArrayList<String>();
    List list2 = new ArrayList();
    System.out.println(list.getClass() == list2.getClass()); // true
}

所以只有这种方式才会使得现有代码不会和之前没有泛型的代码发生冲突。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容