java的泛型與類型擦除

泛型是JDK1.5版本之後有的,它的本質是參數化類型的應用,也就是說所操作的數據類型被指定爲一個參數。這種參數類型可以用在類、接口和方法的創建中,分別被稱爲泛型類、泛型接口和泛型方法。

早在Java語言處於還沒有出現泛型的版本時,只能通過Object是所有類型的父類和類型強制轉換兩個特點的配合來實現類型泛化。例如,在哈希表的存取中,JDK1.5之前使用HashMap的get()方法,返回值就是一個Object對象,由於Java語言裏面所有的類型都繼承於java.lang.Object,所以Object轉型成任何對象都是有可能的。但是也因爲有無限的可能性,就只有程序員和運行期的虛擬機才知道這個Object到底是個什麼類型的對象。在編譯期間,編譯器無法檢查這個Object的強制轉型是否成功,如果僅僅依賴程序員去保障這項操作的正確性,許多ClassCastException的風險就會轉嫁到程序運行期之中。

泛型技術在C#和Java之中的使用方法看似相同,但實現上卻有着根本性的分歧。

C#裏面泛型無亂在程序源碼中、編譯後的IL中(Intermedia Language,中間語言,這時候泛型是一個佔位符),或是運行期的CLR中,都是切實存在的,List<int>與List<String>就是兩個不同的類型,他們在系統運行期生成,有自己的虛方法表和類型數據,這種實現稱爲類型膨脹,基於這種方法實現的泛型成爲真實泛型。

Java語言中的泛型則不一樣,它只是在程序源碼中存在,在編譯後的字節碼文件中,就已經替換爲原來的原生類型(Raw Type,也稱爲裸類型)了,並且在相應的地方插入了強制轉型代碼,因此,對於運行期的Java語言來說,ArrayList<int>與ArrayList<String>就是同一個類,所以泛型技術實際上是Java語言的一顆語法糖,Java語言中的泛型實現方法稱爲類型擦除,基於這種方法實現的泛型成爲僞泛型。

把這段代碼編譯成class文件,然後用反編譯工具進行反編譯後,將會發現泛型都不見了,程序又變回了Java泛型出現之前的寫法,泛型類型都變回了原生類型,如下圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章