Java泛型三:萬用字元詳解extends super
在java泛型中,? 表示萬用字元,代表未知型別,< ? extends Object>表示上邊界限定萬用字元,< ? super Object>表示下邊界限定萬用字元。
萬用字元 與 T 的區別
T:作用於模板上,用於將資料型別進行引數化,不能用於例項化物件。
?:在例項化物件的時候,不確定泛型引數的具體型別時,可以使用萬用字元進行物件定義。
< T > 等同於 < T extends Object>
< ? > 等同於 < ? extends Object>
例一:定義泛型類,將key,value的資料型別進行< K, V >引數化,而不可以使用萬用字元。
public class Container<K, V> {
private K key;
private V value;
public Container(K k, V v) {
key = k;
value = v;
}
}
例二:例項化泛型物件,我們不能夠確定eList儲存的資料型別是Integer
還是Long
,因此我們使用List<? extends Number>
定義變數的型別。
List<? extends Number> eList = null;
eList = new ArrayList<Integer>();
eList = new ArrayList<Long>();
上界型別萬用字元(? extends)
List<? extends Number> eList = null;
eList = new ArrayList<Integer>();
Number numObject = eList.get(0); //語句1,正確
//Type mismatch: cannot convert from capture#3-of ? extends Number to Integer
Integer intObject = eList.get(0 ); //語句2,錯誤
//The method add(capture#3-of ? extends Number) in the type List<capture#3-of ? extends Number> is not applicable for the arguments (Integer)
eList.add(new Integer(1)); //語句3,錯誤
語句1:List<? extends Number>
eList存放Number及其子類的物件,語句1取出Number(或者Number子類)物件直接賦值給Number型別的變數是符合java規範的。
語句2:List<? extends Number>
eList存放Number及其子類的物件,語句2取出Number(或者Number子類)物件直接賦值給Integer型別(Number子類)的變數是不符合java規範的。
語句3:List<? extends Number>
eList不能夠確定例項化物件的具體型別,因此無法add具體物件至列表中,可能的例項化物件如下。
eList = new ArrayList<Integer>();
eList = new ArrayList<Long>();
eList = new ArrayList<Float>();
總結:上界型別萬用字元add方法受限,但可以獲取列表中的各種型別的資料,並賦值給父型別(extends Number)的引用。因此如果你想從一個數據型別裡獲取資料,使用 ? extends 萬用字元。限定萬用字元總是包括自己。
下界型別萬用字元(? super )
List<? super Integer> sList = null;
sList = new ArrayList<Number>();
//Type mismatch: cannot convert from capture#5-of ? super Integer to Number
Number numObj = sList.get(0); //語句1,錯誤
//Type mismatch: cannot convert from capture#6-of ? super Integer to Integer
Integer intObj = sList.get(0); //語句2,錯誤
sList.add(new Integer(1)); //語句3,正確
語句1:List<? super Integer>
無法確定sList中存放的物件的具體型別,因此sList.get
獲取的值存在不確定性,子類物件的引用無法賦值給兄弟類的引用,父類物件的引用無法賦值給子類的引用,因此語句錯誤。
語句2:同語句1。
語句3:子類物件的引用可以賦值給父類物件的引用,因此語句正確。
總結:下界型別萬用字元get方法受限,但可以往列表中新增各種資料型別的物件。因此如果你想把物件寫入一個數據結構裡,使用 ? super 萬用字元。限定萬用字元總是包括自己。
總結
- 限定萬用字元總是包括自己
- 上界型別萬用字元:add方法受限
- 下界型別萬用字元:get方法受限
- 如果你想從一個數據型別裡獲取資料,使用 ? extends 萬用字元
- 如果你想把物件寫入一個數據結構裡,使用 ? super 萬用字元
- 如果你既想存,又想取,那就別用萬用字元
- 不能同時宣告泛型萬用字元上界和下界