java 泛型是java SE 1.5的新特性,泛型的本質是參數化型別,也就是說所操作的資料類型被指定為一個參數。這種參數類型可以用在類、介面和方法的建立中,分別稱為泛型類、泛型介面、泛型方法。
泛型(Generic type 或者 generics)是對 Java 語言的類型系統的一種擴充,以支援建立可以按類型進行參數化類別。可以把型別參數看作是使用參數化型別時指定的類型的一個預留位置,就像方法的形式參數是運行時傳遞的值的預留位置一樣。
可以在集合架構(Collection framework)中看到泛型的動機。例如,Map 類允許您向一個 Map 添加任意類的對象,即使最常見的情況是在給定映射(map)中儲存某個特定類型(比如 String)的對象。
因為 Map.get() 被定義為返回 Object,所以一般必須將 Map.get() 的結果強制類型轉換為期望的類型,如下面的代碼所示:
Map m = new HashMap();
m.put("key", "blarg");
String s = (String) m.get("key");
要讓程式通過編譯,必須將 get() 的結果強制類型轉換為 String,並且希望結果真的是一個 String。但是有可能某人已經在該映射中儲存了不是 String 的東西,這樣的話,上面的代碼將會拋出 ClassCastException。
理想情況下,您可能會得出這樣一個觀點,即 m 是一個 Map,它將 String 鍵映射到 String 值。這可以讓您消除代碼中的強制類型轉換,同時獲得一個附加的類型檢查層,該檢查層可以防止有人將錯誤類型的鍵或值儲存在集合中。這就是泛型所做的工作。
泛型的好處
Java 語言中引入泛型是一個較大的功能增強。不僅語言、類型系統和編譯器有了較大的變化,以支援泛型,而且類庫也進行了大翻修,所以許多重要的類,比如集合架構,都已經成為泛型化的了。
這帶來了很多好處:
1,型別安全。 泛型的主要目標是提高 Java 程式的型別安全。通過知道使用泛型定義的變數的類型限制,編譯器可以在一個高得多的程度上驗證類型假設。沒有泛型,這些假設就只存在於程式員的頭腦中(或者如果幸運的話,還存在於代碼注釋中)。
2,消除強制類型轉換。 泛型的一個附帶好處是,消除原始碼中的許多強制類型轉換。這使得代碼更加可讀,並且減少了出錯機會。
3,潛在的效能收益。 泛型為較大的最佳化帶來可能。在泛型的初始實現中,編譯器將強制類型轉換(沒有泛型的話,程式員會指定這些強制類型轉換)插入產生的位元組碼中。但是更多類型資訊可用於編譯器這一事實,為未來版本的 JVM 的最佳化帶來可能。由於泛型的實現方式,支援泛型(幾乎)不需要 JVM 或類檔案更改。所有工作都在編譯器中完成,編譯器產生類似於沒有泛型(和強制類型轉換)時所寫的代碼,只是更能確保型別安全而已。
Java語言引入泛型的好處是安全簡單。泛型的好處是在編譯的時候檢查型別安全,並且所有的強制轉換都是自動和隱式的,提高代碼的重用率。
泛型在使用中還有一些規則和限制:
1、泛型的型別參數只能是類類型(包括自訂類),不能是簡單類型。
2、同一種泛型可以對應多個版本(因為參數類型是不確定的),不同版本的泛型類執行個體是不相容的。
3、泛型的型別參數可以有多個。
4、泛型的參數類型可以使用extends語句,例如<T extends superclass>。習慣上成為“有界類型”。
5、泛型的參數類型還可以是萬用字元類型。例如Class<?> classType = Class.forName(Java.lang.String);
泛型還有介面、方法等等,內容很多,需要花費一番功夫才能理解掌握並熟練應用。在此給出我曾經瞭解泛型時候寫出的兩個例子(根據看的印象寫的),實現同樣的功能,一個使用了泛型,一個沒有使用,通過對比,可以很快學會泛型的應用,學會這個基本上學會了泛型70%的內容。
之前在上篇使用ArrayList等集合類的時候常常在得到Object類之後進行強制類型轉換才能得到正確的結果,但是現在可能出現一種問題:得到的是一個狗類,然後交給貓類,直接肯定是不行的,強制類型轉換之後程式不會報錯,但是在編譯的時候會出現類型轉換錯誤,泛型就可以簡單的解決這個問題,不用強制轉換直接賦值:
ArrayList <Bird>al=new ArrayList<Bird>();
Bird bd=new Bird("xiaoxiao",2);
al.add(bd);
Bird temp=al.get(0);
System.out.println(temp.getName());
泛型使用範圍也是非常廣泛的,它最重要的作用就是兩點:一是簡單安全,二是提高代碼重用率。泛型的意思就是泛泛的類型,是不確定的,可以看作是一種模版吧,只要是這個形式修改一下資料類型就可以使用了,有泛型方法、泛型類和泛型介面三種類型,看下面的代碼:
Gen<String>gen=new Gen<String>("huhua"); //建立一個泛型對象
gen.showName();
class Gen<T>{
private T o;
public Gen(T o){
this.o=o;
}
public void showName(){
System.out.println(o.getClass.getName());
}
}
只是用泛型T代替了常用的資料類型比如String或者int,其他的原理還是那樣沒變