<? super T> and <? extends T> in Java

原文链接

List<? super T> and List<? extends T>之间有什么区别呢?

我可以常常在List<? super T>中使用add,但是无法对List<? extends T>使用add,这是为啥?

 

Case1:List<? extends T>

对泛型List<? extends Number> foo3的申明可以有以下三种合法的赋值:

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

读:对于上面三种可能的赋值,哪种类型可以保证从List foo3中读数据?

  • 可以读Number,因为List中所有的元素都是Number的子类,自动向上转型。
  • 不可以读Integer,因为List中的元素有可能是指向Double类型的。
  • 不可以读Double,因为List中的元素有可能是指向Integer类型的。

写:对于上面三种可能的赋值,哪种类型可以保证向List foo3中写数据?

  • 不可以写Integer,因为foo3可能指向List<Double>
  • 不可以写Double,因为foo3可能指向List<Integer>
  • 不可以写Number,因为foo3可能指向List<Integer>

 

不能将任何对象添加到List<?extends T>,因为不能保证它真正指向什么类型的列表。唯一的“保证”是只能从中读取得到一个T或T的子类。

 

Case2:List<? super T> 

对泛型List<? super Integer> foo3的申明可以有以下三种合法的赋值:

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

读:对于上面三种可能的赋值,哪种类型可以保证从List foo3中读数据?

  • 不可以读Integer,因为List中的元素有可能是指向List<Number> 或者 List<Object>
  • 不可以读Number,因为List中的元素有可能是指向IList<Object>
  • 仅仅可以读Object类型数据,因为读出来的数据都可以向上转型成Object类型。

写:对于上面三种可能的赋值,哪种类型可以保证向List foo3中写数据?

  • 可以写Integer,因为foo3类型肯定是Integer或者是Integer父类,可以进行向上转型。
  • 可以写Integer的子类,因为添加Integer子类的元素可以自动向上转型。
  • 不可以写Double,因为foo3可能指向ArrayList<Integer>。
  • 不可以写Number,因为foo3可能指向ArrayList<Integer>。
  • 不可以写Object,因为foo3可能指向ArrayList<Integer>。

总结:

  • List<?> : 可以接受任何类型的集合引用赋值,不能添加任何元素,但是可以remove和clear
  • List<? extend T>:get first,只能取,取出来向上转为T,除了null,任何元素都不能往里面放
  • List<? super T>:put first,只能放入T及其子类,能够取出数据,但是类型会丢失,只能返回Object对象

 

PECS

PECS"Producer Extends, Consumer Super".

  • "Producer Extends" - If you need a List to produce T values (you want to read Ts from the list), you need to declare it with ? extends T, e.g. List<? extends Integer>. But you cannot add to this list.

  • "Consumer Super" - If you need a List to consume T values (you want to write Ts into the list), you need to declare it with ? super T, e.g. List<? super Integer>. But there are no guarantees what type of object you may read from this list.

  • If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g. List<Integer>.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值