java_泛型

類型擦除
正確理解泛型概念的首要前提是理解類型擦除(type erasure)。 Java中的泛型基本上都是在編譯器這個層次來實現的。在生成的Java字節代碼中是不包含泛型中的類型信息的。使用泛型的時候加上的類型參數,會被編譯器在編譯的時候去掉。這個過程就稱為類型擦除。如在代碼中定義的List<Object>和List<String>等類型,在編譯之后都會變成List。JVM看到的只是List,而由泛型附加的類型信息對JVM來說是不可見的。Java編譯器會在編譯時盡可能的發現可能出錯的地方,但是仍然無法避免在運行時刻出現類型轉換異常的情況。類型擦除也是Java的泛型實現方式與C++模板機制實現方式之間的重要區別。

很多泛型的奇怪特性都與這個類型擦除的存在有關,包括:
泛型類并沒有自己獨有的Class類對象。比如并不存在List<String>.class或是List<Integer>.class,而只有List.class。
靜態變量是被泛型類的所有實例所共享的。對于聲明為MyClass<T>的類,訪問其中的靜態變量的方法仍然是 MyClass.myStaticVar。不管是通過new MyClass<String>還是new MyClass<Integer>創建的對象,都是共享一個靜態變量。
泛型的類型參數不能用在Java異常處理的catch語句中。因為異常處理是由JVM在運行時刻來進行的。由于類型信息被擦除,JVM是無法區分兩個異常類型MyException<String>和MyException<Integer>的。對于JVM來說,它們都是 MyException類型的。也就無法執行與異常對應的catch語句。

類型擦除的基本過程也比較簡單,首先是找到用來替換類型參數的具體類。這個具體類一般是Object。如果指定了類型參數的上界的話,則使用這個上界。把代碼中的類型參數都替換成具體的類。同時去掉出現的類型聲明,即去掉<>的內容。比如T get()方法聲明就變成了Object get();List<String>就變成了List。接下來就可能需要生成一些橋接方法(bridge method)。這是由于擦除了類型之后的類可能缺少某些必須的方法。比如考慮下面的代碼:
class MyString implements Comparable<String> { public int compareTo(String str) { return 0; }}
當類型信息被擦除之后,上述類的聲明變成了class MyString implements Comparable。但是這樣的話,類MyString就會有編譯錯誤,因為沒有實現接口Comparable聲明的int compareTo(Object)方法。這個時候就由編譯器來動態生成這個方法。

通配符

private <E extends View> E $(int id) {
E e = (E) findViewById(id);
return e;
}

Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(sourceObject);

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 開發人員在使用泛型的時候,很容易根據自己的直覺而犯一些錯誤。比如一個方法如果接收List作為形式參數,那么如果嘗試...
    時待吾閱讀 1,073評論 0 3
  • 2.6 Java泛型詳解 Java泛型是JDK5中引入的一個新特性,允許在定義類和接口的時候使用類型參數(type...
    jianhuih閱讀 700評論 0 3
  • 開發人員在使用泛型的時候,很容易根據自己的直覺而犯一些錯誤,比如一個方法如果接收List 作為形式參數,那么如果嘗...
    azmohan閱讀 137評論 0 0
  • 不知各位,有沒有聽李笑來說過《五只猴子吃香蕉》的笑話?那幾只不明就里白白挨打的猴子真切的告訴我們:"如果可...
    簡單生活enjoylily閱讀 584評論 0 0
  • 父親的話 父親的話驚醒了我三十年的人生,我人生的后幾十年也會永遠被提醒。 說實話,小時候,父親在我眼里絕對和藹、絕...
    清水溪貝閱讀 838評論 1 6