1、定義
什麼是泛型,看表面的意思,泛型就是指廣泛的、普通的類型。在java中是指把類型明確的工作推遲到創建對象或調用方法的時候纔去明確的特殊的類型。
可一看一個簡單的例子:
List<String> strings = new ArrayList<String>();
strings.add("a String");
String aString = strings.get(0);
可以看到,通過菱形語法('<>')可以將List內元素的類型限定爲String類型。
需要注意的是<>內的類型只能是引用類型,當然對於基本類型,可以使用對應的包裝類型。
2、使用泛型的好處
(1)首先就像上面那個例子一樣,使用泛型能夠限定集合中,如List, Set中元素的類型,保證一個集合中只有一個類型。(這樣也就能夠使用增強for來遍歷集合)
(2)程序也能更加健壯(只要在編譯時期沒有出現警告,那麼運行時期就不會出現ClassCastException異常)
3、泛型的基礎
1)泛型類
泛型類也就是把泛型定義在類上,這樣用戶在使用類的時候才把類型給確定下來。
public class ObjectTool<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
可以看到上面這個程序,在使用時如果定義了類型,那麼在使用時就可以不用進行強制類型轉換,直接就可以得到一個T類型的對象。
(2)泛型方法
有時候只關心某個方法,那麼使用泛型時可以不定義泛型類,而是隻定義一個泛型方法,如下
public <T> void show(T t) {
System.out.println(t);
}
需要注意一下定義的格式,泛型必須得先定義才能夠使用。
(3)繼承關係
泛型類在繼承時,可以明確父類(泛型類)的參數類型,也可以不明確。
現在我們有如下的泛型類
//泛型類
public interface Inter<T> {
public abstract void show(T t);
}
①明確類型
//在實現泛型類時明確父類的類型
public class InterImpl implements Inter<String> {
@Override
public void show(String s) {
System.out.println(s);
}
}
②不明確類型
public class InterImpl<T> implements Inter<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
(4)類型通配符
(1)無界
類型通配符我感覺上和泛型方法差不多,只是不用在使用前進行定義,例子如下:
public void processElements(List<?> elements){
for(Object o : elements){
System.out.println(o);
}
}
"?"可以接收任何類型。
(2)上界
public void processElements(List<? extends A> elements){
for(A a : elements){
System.out.println(a.getValue());
}
}
這種情況下能夠接收A類或者A類的子類。
(3)下界
public static void insertElements(List<? super A> list){
list.add(new A());
list.add(new B());
list.add(new C());
}
這種情況下能夠接收A類或者A類的父類
(4)類型通配符和泛型方法
我認爲這兩種方式是差不多的,不過在使用時,如果參數之間是有依賴關係的,那麼可以使用泛型方法,否則就使用類型通配符。(如果一個方法的返回值、某些參數的類型依賴另一個參數的類型就應該使用泛型方法,因爲被依賴的類型如果是不確定的?,那麼其他元素就無法依賴它)。
(5)開發相關
泛型通配符< ? extends T >來接收返回的數據,此寫法的泛型集合不能使用 add 方 法, 而< ? super T >不能使用 get 方法,做爲接口調用賦值時易出錯。
這個怎麼來理解呢,當我們使用extends時,我們可以讀元素,因爲元素都是A類或子類,可以放心的用A類拿出。
當使用super時,可以添加元素,因爲都是A類或父類,那麼就可以安全的插入A類。