天天看點

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

    .