天天看点

<? super T> and <? extends T> in JavaCase1:List<? extends T>读:对于上面三种可能的赋值,哪种类型可以保证从List foo3中读数据?写:对于上面三种可能的赋值,哪种类型可以保证向List foo3中写数据? Case2:List<? super T> 读:对于上面三种可能的赋值,哪种类型可以保证从List foo3中读数据?写:对于上面三种可能的赋值,哪种类型可以保证向List foo3中写数据?总结:

原文链接

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中的元素有可能是指向I

    List<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 

    T

    s 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 

    T

    s 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>

    .