java 泛型

很多朋友对Java的泛型不是很理解,很多文章写的已不是很清楚,这篇博客对java泛型进行 一个总结。

  • 泛型的转换:
List<Number> foo1 = new ArrayList<Integer>();//illegal 

很多朋友会写出上面的代码,但会报如下错误:Type mismatch: cannot convert from ArrayList<Integer> to List<Number>尽管Interge是Number的子类,但是ArrayList<Integer>不是List<Number>的子类,所以报错。下图可以很好解释这个问题。

[图片上传失败...(image-a39134-1512892860416)]

  • java泛型的通配符?
    这里可以分为两类(1)? extends T (2) ? super T.
  • 1.1很多朋友对这两个不是很理解,也不知道上面时候用,我们知道java中提供泛型技术,是为了提供安全检查的,使得我们写的代码更加的健壮。
public static void print_e(List<? extends Number> list){  
        for(Number n : list){  
            System.out.println(n);  
        }  
    }  

上面一个函数,我们可以传递如下的参数

List<Integer> list_i = new ArrayList<Integer>();  
        for(int i=0;i<10;i++){  
            list_i.add(i);  
        }  
        List<Double> list_d = new ArrayList<Double>();  
        for(int i=0;i<10;i++){  
            list_d.add(i+0.0);  
        }  
        print_e(list_i);  
        print_e(list_d);  

使得我们写的代码即具有通用型有可以提供必要的安全检查,当然print_e你可以写出如下形式,这里就不具有安全检查的效果了。

void print_e(List list)  

但是经常有的朋友写出如下的代码,我们举一个stackoverflow上的一个例子:

List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)  
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number 
List<? extends Number> foo3 = new ArrayList<Double>();  // Double extends Number  

上面的代码都是可以通过的,但是如果你向foo3中添加一个元素,比如foo3.add(new Integer(1)),讲话如下错误:
The method add(capture#1-of ? extends Number) in the type List<capture#1-of ? extends Number> is not applicable for the arguments (Integer)
很多人觉得奇怪,Integer明明是Number的子类,为什么添加不进去了。

List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)  

stackoverflow上一个朋友是这样解释的,解释的很好,借用他的解释如下:

Reading - Given the above possible assignments, what type of object are you guarenteed to read from List foo3:  
  
You can read a Number because any of the lists that could be assigned to foo3 contain a Number or a subclass of Number.  
You can't read an Integer because foo3 could be pointing at a List<Double>.  
You can't read a Double because foo3 could be pointing at a List<Integer>.  
Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:  
  
You can't add an Integer because foo3 could be pointing at a List<Double>.  
You can't add a Double because foo3 could be pointing at a List<Integer>.  
You can't add a Number because foo3 could be pointing at a List<Integer>.  
You can't add any object to List<? extends T> because you can't guarantee what kind of List it is really pointing to, so you can't guarantee that the object is allowed in that List. The only "guarantee" is that you can only read from it and you'll get a T or subclass of  T.  

因为 List<? extends Number> foo3 中你既可以添加一个Integer的有可以添加一个Double的,所以编译器不知道你具体添加到的是哪一种类型,所以编译器不允许你添加元素

  • 1.2再来看一下? super T的例子:
List<? super Integer> foo3 = new ArrayList<Integer>();  // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>();   // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>();   // Object is a superclass of Integer

stackoverflow的解释如下:

Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from List foo3:  
  
You aren't guaranteed an Integer because foo3 could be pointing at a List<Number> or List<Object>.  
You aren't guaranteed an Number because foo3 could be pointing at a List<Object>.  
The only guarantee is that you will get an instance of an Object or subclass of Object (but you don't know what subclass).  
Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:  
  
You can add an Integer because an Integer is allowed in any of above lists.  
You can add an instance of a subclass of Integer because an instance of a subclass of Integer is allowed in any of the above lists.  
You can't add a Double because foo3 could be pointing at a ArrayList<Integer>.  
You can't add a Number because foo3 could be pointing at a ArrayList<Integer>.  
You can't add a Object because foo3 could be pointing at a ArrayList<Integer>.  

foo3你是不能读的,读出报如下类似错误Type mismatch: cannot convert from capture#2-of ? super Integer to Integer
因为foo3中的元素有可能是Integer,Number或者是Object的,所以编译器不知道读出的是什么类型,所以不允许你读出元素。

总的来说,你要读就用? extends T,你要写就就用 ? super T,你既要读,又要写,你就不用泛型直接定义List list,这样就好了,如果没还没有看明白,直接看stackoverflow上的这篇文章,解释的很好
http://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java
这一篇的将泛型擦除的,也可以看一下
http://blog.csdn.NET/caihaijiang/article/details/6403349

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

推荐阅读更多精彩内容

  • 参考 & 推荐 Effective Java(2nd Edition)December, 2017 马上就要出版第...
    xiaofudeng阅读 8,767评论 1 11
  • 开发人员在使用泛型的时候,很容易根据自己的直觉而犯一些错误。比如一个方法如果接收List作为形式参数,那么如果尝试...
    时待吾阅读 1,033评论 0 3
  • 我们知道,使用变量之前要定义,定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值。 假如我们现在...
    今晚打肉山阅读 967评论 0 1
  • 为什么需要泛型? 通过泛型可以定义类型安全的数据结构,而无须使用实际的数据类型(可扩展)。这能够显著提高性能并得到...
    一只好奇的茂阅读 1,250评论 2 39
  • 泛型的好处 使用泛型的好处我觉得有两点:1:类型安全 2:减少类型强转 下面通过一个例子说明: 假设有一个Tes...
    德彪阅读 1,092评论 0 0