泛型<?super T> 和<? extends T>区别

原创 2017年09月07日 16:13:56

Java 泛型

关键字说明

  • ? 通配符类型
  • <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
  • <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
首先,泛型的出现时为了安全,所有与泛型相关的异常都应该在编译期间发现,因此为了泛型的绝对安全,java在设计时做了相关的限制:List<? extends E>表示该list集合中存放的都是E的子类型(包括E自身),由于E的子类型可能有很多,但是我们存放元素时实际上只能存放其中的一种子类型(这是为了泛型安全,因为其会在编译期间生成桥接方法<Bridge Methods>该方法中会出现强制转换,若出现多种子类型,则会强制转换失败),
例子如下:
List<? extends Number> list=new ArrayList<Number>();
list.add(4.0);//编译错误
list.add(3);//编译错误
上例中添加的元素类型不止一种,这样编译器强制转换会失败,为了安全,Java只能将其设计成不能添加元素。虽然List<? extends E>不能添加元素,但是由于其中的元素都有一个共性--有共同的父类,因此我们在获取元素时可以将他们统一强制转换为E类型,我们称之为get原则。对于List<? super E>其list中存放的都是E的父类型元素(包括E),我们在向其添加元素时,只能向其添加E的子类型元素(包括E类型),这样在编译期间将其强制转换为E类型时是类型安全的,因此可以添加元素,
例子如下:
List<? super Number> list=new ArrayList<Number>();
list.add(2.0);
list.add(3.0);
但是,由于该集合中的元素都是E的父类型(包括E),其中的元素类型众多,在获取元素时我们无法判断是哪一种类型,故设计成不能获取元素,我们称之为put原则。实际上,我们采用extends,super来扩展泛型的目的是为了弥补例如List<E>只能存放一种特定类型数据的不足,将其扩展为List<? extends E> 使其可以接收E的子类型中的任何一种类型元素,这样使它的使用范围更广。
List<? super E>同理。

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子类型限定的通配符可以向泛型对象读取。——《Core Java》
版权声明:本文为博主原创文章,未经博主允许不得转载。

Java 泛型 <? super T> 中 super 怎么 理解<?与 extends> 有何不同?

Java 泛型 中 super 怎么 理解 有何不同? 问题引入: // compile error // List appList2 = new ArrayList();...
  • lswlov
  • lswlov
  • 2016年11月26日 17:33
  • 1136

java泛型中<? super T> 和<? extends T>的区别---转发

java泛型中
  • juzipeek
  • juzipeek
  • 2016年02月23日 11:44
  • 479

泛型之<T extends Comparable<? super T>>

表示T类型只能是Comparable的zi
  • gy40235
  • gy40235
  • 2014年05月03日 10:52
  • 1011

Java学习之道:简述泛型通配符<? extends T>和<? super T>

和含有JAVA5.0的新的概念。由于它们的外表导致了很多人误解了它们的用途: 1.首先你很容易误解它为继承于T的所有类的集合,这是大错特错的,相信能看下去你一定见过或用过List吧?为什么我说理...
  • u011511429
  • u011511429
  • 2014年08月11日 10:44
  • 2198

Java泛型通配符<? extends T>与<? super T>

关键字说明 ● ? 通配符类型 ● 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 ● 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类...
  • qq_27789551
  • qq_27789551
  • 2016年08月22日 11:00
  • 1771

理解泛型通配符(List<? extends T > & List< ? super T>)

List是T的某种子类的一个集合,所以List中的方法的参数涉及到通配符的都不能被调用。因为编译器不知道集合具体装的是T的哪个子类对象(subclass) ,所以不可以向集合中添加T的子类对象,包括T...
  • u013852032
  • u013852032
  • 2016年03月24日 17:00
  • 2464

java泛型(二)? super T 和 ? extends T 消费者和生产者

经常发现有List、Set的声明,是什么意思呢?表示包括T在内的任何T的父类,表示包括T在内的任何T的子类,下面我们详细分析一下两种通配符具体的区别。 extends List foo3的通配符声明,...
  • Victor_Cindy1
  • Victor_Cindy1
  • 2016年01月04日 23:09
  • 750

<? extends T> 和 <? super T>的作用

和直接有什么区别呢? 这里如果是前者那么会编译报错; 原因:前者的? 直接是在T的子类里面的具体的某一个类,但是编译器无法确定到底是哪一个子类,这样写就是为了不能add操作。 也就是说这个list是...
  • atares0223
  • atares0223
  • 2016年09月08日 14:38
  • 2371

Java中<? extends T>和<? super T>的理解

? 通配符类型-
  • jdsjlzx
  • jdsjlzx
  • 2017年04月23日 00:45
  • 2841

List<super T> 和List<extends T>详解

代码中经常发现有List、Set的声明,是什么意思呢? 表示包括T在内的任何T的父类,表示包括T在内的任何T的子类,下面我们详细分析一下两种通配符具体的区别。 extends List foo3...
  • lebsharing
  • lebsharing
  • 2015年11月04日 14:09
  • 1165
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:泛型<?super T> 和<? extends T>区别
举报原因:
原因补充:

(最多只允许输入30个字)