首頁 > Java > java教程 > 主體

深入了解Java中的泛型

零下一度
發布: 2017-07-18 09:47:09
原創
1499 人瀏覽過

         泛型的定義:泛型是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與List就是兩個不同的類型,它們在系統運行期生成,有自己的虛方法表和類型數據,這種實現稱為類型膨脹,基於這種方法實現的泛型被稱為真實泛型。

  Java語言中的泛型則不一樣,它只在程式原始碼中存在,在編譯後的字節碼檔案中,就已經被替換為原來的原始型別(Raw Type,也稱為裸類型)了,並且在相應的地方插入了強制轉型代碼,因此對於運行期的Java語言來說,ArrayList與ArrayList就是同一個類別。所以說泛型技術其實是Java語言的一顆語法糖,Java語言中的泛型實作方法稱為型別擦除,基於此方法實作的泛型稱為偽泛型。 (類型擦除在後面在學習)

  使用泛型機制編寫的程式碼比那些雜亂的使用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,直接限定了list集合中只能含有String類型的元素。

 

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中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!