一、泛型概念的提出
首先來看下面一個簡單的栗子:
public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
List list = new ArrayList();
list.add("abc");
list.add("edf");
list.add(55);
for(int i=0;i<list.size();i++){
String temp = (String) list.get(i);
System.out.println(temp);
}
}
}
abc
edf
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at demo.Test1.main(Test1.java:22)
可以看出,在輸出55的時候報錯 :ClassCastException(),類型轉換錯誤,通常是“當前者的域小於後者的域時候出現 ”,例如前者A是子類的對象,而後者B是父類的對象。若A=B,則會拋出該錯誤。
再仔細看看代碼:
定義了一個List類型的集合,先向其中加入了兩個字符串類型的值,隨後加入一個Integer類型的值。這是完全允許的,因爲此時list默認的類型爲Object類型。在之後的循環中,由於忘記了之前在list中也加入了Integer類型的值或其他編碼原因,很容易出現類似ClassCastException()的錯誤。編譯階段正常,而運行時會出現“java.lang.ClassCastException”異常。因此,導致此類錯誤編碼過程中不易發現。
通過以上的栗子可以看到,在將字符串裝入集合時,編譯時無法自動識別錯誤,但是在取出它時會報錯;還有在取出時,需要強制轉換類型!
那麼有什麼辦法使得集合記住自己裝入的類型,從而阻止其他類型繼續裝入呢?答案就在“泛型”。
二、什麼是泛型?
泛型,即“參數化類型”。具體來說就是,原來在定義變量、方法、類時使用的int ,String,void等進行“參數化”,原來具體的類型現在成爲了不確定的。類似於在定義方法時會傳入形參,而在調用方法時傳入實參。
把上面的栗子採用泛型改寫如下:
public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
List <String> list = new ArrayList();
list.add("abc");
list.add("edf");
// list.add(55); // 編譯錯誤
for(int i=0;i<list.size();i++){
String temp = list.get(i);
System.out.println(temp);
}
}
}
在上面 Code中,加入1個integer類型的數據 55 時會提示編譯錯誤,這是因爲在List<String>中限定了加入的元素只能是String 類型的。這樣在取出元素時,就不需要進行強轉,因爲加入的時候就已經確定好了。
泛型不僅有泛型參數,泛型類,還有泛型方法!看以下的栗子:
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Gen<String> gen = new Gen<String>("abc");
gen.showType();
System.out.println("o=="+(gen.getData()));
}
}
class Gen<T>{
private T o;
public Gen(T a){
o=a;
}
//泛型方法
public T getData(){
return o;
}
//顯示o的類型
public void showType(){
System.out.println("類型是:"+o.getClass().getName());
}
}
泛型的主要好處在於:在編譯時檢查類型安全,並且所有的強制轉換都是自動和隱式的,提高代碼的重用率。