1. 程式人生 > 其它 >List<? extends T>和List<? super T>之間由什麼區別?

List<? extends T>和List<? super T>之間由什麼區別?

<? extends T>表示型別的上界,也就是說,引數化的型別可能是T或者T的子類。例如,下面的寫法都是合法的賦值語句:、

List<? extends Number> list = new ArrayList<Number>();
List<? extends Number> list = new ArrayList<Integer>(); //Integer是Number的子類
List<? extends Number> list = new ArrayList<Float>();	//Float也是Number的子類

<? extends T>被設計為用來讀資料的泛型(只能讀取型別為T的元素),原因如下:

(1)在上面賦值的示例中,對讀資料進行分析

1)不管給list如何賦值,可以保證list裡面存放的一定是Number型別或其子類,因此,可以從list列表裡面讀取Number型別的值。

2)不能從list中讀取Integer,因此list裡面存放的是Float值,同理,也不可以從list裡面讀取Float。

(2)對讀資料進行分析

1)不能向list中寫Number,因為list中有可能存放的是Float。

2)不能向list中寫Integer,因為list中有可能存放的是Float。

3)不能向list中寫Float,因為list中有可能存放的是Integer。

從上面的分析可以發現,只能從List<? extends T>讀取T,因為無法確定它實際指向列表的型別,從而無法確定列表裡面存放的實際的型別,所以,無法向列表裡面新增元素。

<? super T>表示型別下界,也就是說,引數化的型別是此型別的超型別(父型別)。

List<? super Float> list = new ArrayList<Float>();
List<? super Float> list = new ArrayList<Number>();	//Number是Float的父類
List<? super Float> list = new ArrayList<Object>();	//Float也是Number的子類

<? super T>被設計為用來寫資料的泛型(只能寫入T或T的子類型別),不能用來讀,分析如下

(1)讀資料

無法保證list裡面一定存放的是Float型別或者Number型別,因為有可能存放的是Object型別,唯一能確定的是list裡面存放的是Object或其子類,但是無法確定具體子類的型別。

正是由於無法確定list裡面存放資料的型別,因此,無法從list裡面讀取資料。

(2)寫資料

1)可以向list裡面寫入Float型別的資料(不管list裡面實際存放的是Float,Number或者Object,寫入Float都是允許的);同理,也可以向list裡面新增Float子類型別的元素。

2)不可以向list裡面新增Number或Object型別的資料,因為list中可能存放的是Float型別的資料。

下面給出兩個泛型使用的場景

 public static <T> void copy(List<? super T> dest,List<? extends T> src){
        for (int i = 0; i < src.size(); i++) {
            dest.set(i,src.get(i));
        }
    }