泛型的定義:泛型是JDK 1.5的新特性,它本質上是參數化的類型(Parameterized Type)的應用,也就是說所操作的資料型態被指定為一個參數,在用到的時候在指定具體的型別。這種參數類型可以用在類別、介面和方法的建立中,分別稱為泛型類別、泛型介面和泛型方法。
泛型思想早在C++語言的模板(Templates)中就開始生根發芽,在Java語言處於還沒有出現泛型的版本時,只能透過Object是所有類型的父類和類型強制轉換兩個特點的配合來實現類型泛化。例如在哈希表的存取中,JDK 1.5之前使用HashMap的get()方法,回傳值就是一個Object對象,由於Java語言裡面所有的型別都繼承於java.lang.Object,那麼Object轉型為任何對象成都是有可能的。但也因為有無限的可能性,就只有程式設計師和運作期間的虛擬機器才知道這個Object到底是個什麼類型的物件。在編譯期間,編譯器無法檢查這個Object的強制轉型是否成功,如果只依賴程式設計師去保障這項操作的正確性,許多ClassCastException的風險就會被轉嫁到程式執行期間。
泛型技術在C#和Java之中的使用方式看似相同,但實現上卻有著根本性的分歧,C#裡面泛型無論在程式原始碼中、編譯後的IL中(Intermediate Language ,中間語言,這時候泛型是一個佔位符)或是運行期的CLR中都是切實存在的,List
Java語言中的泛型則不一樣,它只在程式原始碼中存在,在編譯後的字節碼檔案中,就已經被替換為原來的原始型別(Raw Type,也稱為裸類型)了,並且在相應的地方插入了強制轉型代碼,因此對於運行期的Java語言來說,ArrayList
使用泛型機制編寫的程式碼比那些雜亂的使用Object變量,然後再進行強制類型轉換的程式碼具有更好的安全性和可讀性。泛型對於集合類別來說尤其有用。
1、為什麼要使用泛型
這裡我們兩個看一段程式碼;
List list = new ArrayList(); list.add("CSDN_SEU_Cavin"); list.add(100); for (int i = 0; i < list.size(); i++) { String name = (String) list.get(i); //取出Integer时,运行时出现异常 System.out.println("name:" + name); }
本例向list型別集合中加入了一個字串類型的值和一個Integer類型的值。 (這樣合法,因為此時list預設的類型為Object類型)。在之後的循環中,由於忘記了先前在list中也加入了Integer類型的值或其他原因,執行時會出現java.lang.ClassCastException異常。為了解決這個問題,泛型應運而生。
2、泛型的使用
泛型讓程式設計人員能夠使用型別抽象,通常用於集合內。
List<String> list = new ArrayList<String>();
這裡這樣寫,上面那段循環取值得方式就不會報錯,而且也不需要進行類型的強制轉換。透過List
3、泛型只在編譯期間有效
我們在使用泛型的時候也要了解到泛型的編譯時怎樣的,因此在這裡,我們需要特別的注意是:泛型,只是在程式碼編譯成class檔期間有效
AyyayList<String> a = new ArrayList<String>(); ArrayList b = new ArrayList(); Class c1 = a.getClass(); Class c2 = b.getClass(); System.out.println(a == b);
上面程式的輸出結果為true。是因為所有反射的操作都是在運行時進行的,既然為true,就證明了編譯之後,程式會採取去泛型化的措施。
也就是說Java中的泛型,只在編譯階段有效。在編譯過程中,正確檢驗泛型結果後,會將泛型的相關資訊擦出,並且在物件進入和離開方法的邊界處添加類型檢查和類型轉換的方法。也就是說,成功編譯過後的class檔案中是不包含任何泛型資訊的。泛型資訊不會進入到運行時階段。
下面這段程式碼透過Java的反射機制很好的解釋了泛型只在編譯期間有效
ArrayList<String> a = new ArrayList<String>(); a.add("CSDN_SEU_Cavin"); Class c = a.getClass(); try{ Method method = c.getMethod("add",Object.class); method.invoke(a,100); System.out.println(a); //[CSDN_SEU_Cavin, }catch(Exception e){ e.printStackTrace();
4、泛型類別和泛型方法
public static class FX<T> { private T ob; // 定义泛型成员变量 public FX(T ob) { this.ob = ob; } public T getOb() { return ob; } public void showTyep() { System.out.println("T的实际类型是: " + ob.getClass().getName()); } } public static void main(String[] args) { FX<Integer> intOb = new FX<Integer>(100); intOb.showTyep(); System.out.println("value= " + intOb.getOb()); //java.lang.Integer System.out.println("----------------------------------"); FX<String> strOb = new FX<String>("CSDN_SEU_Calvin"); strOb.showTyep(); System.out.println("value= " + strOb.getOb()); //value= 100 }
5.泛型的好處
(1)型別安全。
透過知道使用泛型定義的變數的型別限制,編譯器可以更有效地提升Java程式的型別安全性。
(2)消除強制型別轉換。
消除原始程式碼中的許多強制型別轉換。這使得程式碼更加可讀,並且減少了出錯機會。所有的強制轉換都是自動和隱式的。
(3)提高效能
以上是深入了解Java中的泛型的詳細內容。更多資訊請關注PHP中文網其他相關文章!