引自:http://sharewind.iteye.com/blog/1622164

关键字说明

  • ? 通配符类型
  • <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
  • <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object

extends 示例

static class Food{}
static class Fruit extends Food{}
static class Apple extends Fruit{}
static class RedApple extends Apple{} List<? extends Fruit> flist = new ArrayList<Apple>();
// complie error:
// flist.add(new Apple());
// flist.add(new Fruit());
// flist.add(new Object());
flist.add(null); // only work for null

List<? extends Frut> 表示 “具有任何从Fruit继承类型的列表”,编译器无法确定List所持有的类型,所以无法安全的向其中添加对象。可以添加null,因为null 可以表示任何类型。所以List 的add 方法不能添加任何有意义的元素,但是可以接受现有的子类型List<Apple> 赋值。

Fruit fruit = flist.get(0);
Apple apple = (Apple)flist.get(0);

由于,其中放置是从Fruit中继承的类型,所以可以安全地取出Fruit类型。

flist.contains(new Fruit());
flist.contains(new Apple());

在使用Collection中的contains 方法时,接受Object 参数类型,可以不涉及任何通配符,编译器也允许这么调用。

super 示例

List<? super Fruit> flist = new ArrayList<Fruit>();
flist.add(new Fruit());
flist.add(new Apple());
flist.add(new RedApple()); // compile error:
List<? super Fruit> flist = new ArrayList<Apple>();

List<? super Fruit> 表示“具有任何Fruit超类型的列表”,列表的类型至少是一个 Fruit 类型,因此可以安全的向其中添加Fruit 及其子类型。由于List<? super Fruit>中的类型可能是任何Fruit 的超类型,无法赋值为Fruit的子类型Apple的List<Apple>.

// compile error:
Fruit item = flist.get(0);

因为,List<? super Fruit>中的类型可能是任何Fruit 的超类型,所以编译器无法确定get返回的对象类型是Fruit,还是Fruit的父类Food 或 Object.

小结

extends 可用于的返回类型限定,不能用于参数类型限定。
super 可用于参数类型限定,不能用于返回类型限定。
>带有super超类型限定的通配符可以向泛型对易用写入,带有extends子类型限定的通配符可以向泛型对象读取。

我的理解:

泛化:给容器指定一种对象类型。在java中,子类可以赋值给父类容器,即向上赋值;而父类不可以赋值给子类容器,因为向下赋值需要增添新的属性等信息,这是无法完成的,即不能向下赋值。

===》List< ? super Fruit >

  • 表示List里存放的都是 Fruit 和 Fruit 的父类,但是在编译的时候并不清楚具体是哪个父类。
  • 直接向 List 赋值时,必须满足容器对象要求,从而必须赋值为 Fruit 或 Fruit 的父类。 因为编译时,完全符合要求,所以可以通过编译。在运行时,必须要确定 List 里放的是什么类型的对象。如果放 Fruit 子类,那么根本不知道要把 Fruit 子类泛化为哪种类型,从而最终运行时 List 存放的对象类型是不确定的。
  • 可以向 List add 任何 Fruit 和 Fruit 的子类。因为在编译时,可以确定 List 中至少是 Fruit,因此 Fruit 和 Fruit 子类 至少可以向上赋值给 Fruit,当然也可能赋值给 Fruit 父类,所以编译通过。 而在运行时,List 中存放的具体是 Fruit 的哪个父类已经确定了,add 的元素会直接转换为该父类,所以运行通过。
  • super 用于add元素,不用于 get 元素。因为编译时不确定是哪个父类,由于泛化限定,get只能赋值给 当前类型及其父类,那么只能赋值给 Object 对象了。所以 Object o = flist.get(0) 是可以的。

===》List< ? extends Fruit >

  • 表示 List 里存放的都是 Fruit 和 Fruit 的子类,但是在编译的时候并不清楚具体是哪个子类。
  • 直接向 List 赋值时,必须满足容器对象要求,从而必须赋值为 Fruit 或 Fruit 的子类。这里根本不可能赋值为父类,因为这违反了泛化的基本要求。
  • get元素可以赋值给 Fruit 和 Fruit 父类。因为 List 中存放的至多是 Fruit 类,所以向上赋值时, Fruit 和 Fruit 父类都是满足要求的。
  • extends 用于get元素,不用于add元素。不可以向 List add 元素。因为编译时不确定 List 中存放的是哪个 Fruit 子类,如果 add 了某个子类,eg. Orange,而实际存储的是 Apple,那么根本类型就不匹配。所以只能add null。

java 泛型通配符 extends, super的更多相关文章

  1. JAVA 泛型 通配符? extends super限定,实例区分extends super限定的作用用法

    java泛型中的关键字 ? 表示通配符类型 <? extends T> 既然是extends,就是表示泛型参数类型的上界,说明参数的类型应该是T或者T的子类. <? super T& ...

  2. JAVA 泛型通配符 ? EXTENDS SUPER 的用法

    1. <? extends Hero> ArrayList heroList<? extends Hero> 表示这是一个Hero泛型或者其子类泛型heroList 的泛型可能 ...

  3. Java 泛型 通配符类型

    Java 泛型 通配符类型 @author ixenos 摘要:限定通配符类型.无限定通配符类型.与普通泛型区别.通配符捕获 通配符类型 通配符的子类型限定(?都是儿孙) <? extends ...

  4. Java泛型 通配符? extends与super

    Java 泛型 关键字说明 ? 通配符类型 <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 <? super T> 表示类型下界(Java ...

  5. Java 之泛型通配符 ? extends T 与 ? super T 解惑

    简述 大家在平时的工作学习中, 肯定会见过不少如下的语句: List<? super T> List<? extends T> 我们都知道, 上面的代码时关于 Java 泛型的 ...

  6. 浅谈Java泛型之<? extends T>和<? super T>的区别

    关于Java泛型,这里我不想总结它是什么,这个百度一下一大堆解释,各种java的书籍中也有明确的定义,只要稍微看一下就能很快清楚.从泛型的英文名字Generic type也能看出,Generic普通. ...

  7. Java泛型中extends和super的理解(转)

    E – Element (在集合中使用,因为集合中存放的是元素) T – Type(Java 类) K – Key(键) V – Value(值) N – Number(数值类型) ? – 表示不确定 ...

  8. java泛型中extends 和 super的区别

    一般对泛型中extends 和 super 的区别是这样介绍的: 关键字说明 ? 通配符类型 <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 < ...

  9. JAVA泛型知识--> <? extends T>和<? super T>

    <? extends T> 和 <? super T> 是Java泛型中的“通配符(Wildcards)” 和 “边界(Bounds)”的概念 <? extends T& ...

随机推荐

  1. C语言中关于float和double的输入输出格式

    1.对于double类型,输入格式为scanf("%lf %lf", &foo, &bar); 对于float类型,输入格式为scanf("%f %f, ...

  2. EL表达式隐含对象

    EL表达式语言中定义了11个隐含对象,使用这些隐含对象可以很方便地获取web开发中的一些常见对象,并读取这些对象的数据. 语法:${隐式对象名称}  :获得对象的引用 <%@ page lang ...

  3. 三、android中Handle类的用法

    当我们在处理下载或是其他需要长时间执行的任务时,如果直接把处理函数放Activity的OnCreate或是OnStart中,会导致执行过程中整个Activity无响应,如果时间过长,程序还会挂掉.Ha ...

  4. Java中Properties类的学习总结

    学习目标: 1.认识properties文件,理解其含义,会正确创建properties文件. 2.会使用java.util.Properties类来操作properties文件. 一.认识prope ...

  5. Linux中shell命令的用法和技巧

    使用Linux shell是我每天的基本工作,但我经常会忘记一些有用的shell命令和l技巧.当然,命令我能记住,但我不敢说能记得如何用它执行某个特定任务.于是,我开始在一个文本文件里记录这些用法,并 ...

  6. 找不到命名空间命名空间:System.Windows.Forms

    System.Windows.Forms在system.windows.forms.dll中.需要添加引用.在解决方案资源管理器中的引用上单击右键,选择添加引用.找到System.windows.fo ...

  7. .NET使用QRCodeEncoder生成二维码

    ThoughtWorks.QRCode.dll版本 1.0.2774.19990 代码如下: /// <summary> /// 生成二维码图片 /// </summary> ...

  8. 《iOS开发指南》要改iOS8版本了,听听您的意见?

    <iOS开发指南>要改iOS8版本了,听听您的意见?参加问卷同学均可获得智捷课堂50元代金卡一张,同时抽取一名同学赠送即将出版的基于iOS8的<iOS开发指南>一本,欢迎大家填 ...

  9. ThinkPHP中的视图

    ThinkPHP中的视图View 1.什么是视图View 所谓的视图就是用户可视化操作界面. 2.视图View组成 view类(模板引擎类似Smarty) 模板文件(html模板) 3.视图的定义 默 ...

  10. WebServiceException

    在用cxf做webservice的时候,在写客户端程序的时候,出现以下异常: Could not find wsdl:binding operation info for web method tes ...