Java泛型的內部原理:類型擦除並舉例說明

原文:http://blog.csdn.net/wisgood/article/details/11762427

一、Java泛型的實現方法:類型擦除

前面已經說了,Java的泛型是僞泛型。爲什麼說Java的泛型是僞泛型呢?因爲,在編譯期間,所有的泛型信息都會被擦除掉。正確理解泛型概念的首要前提是理解類型擦出(type erasure)。

Java中的泛型基本上都是在編譯器這個層次來實現的。在生成的Java字節碼中是不包含泛型中的類型信息的。使用泛型的時候加上的類型參數,會在編譯器在編譯的時候去掉。這個過程就稱爲類型擦除。

如在代碼中定義的List<object>和List<String>等類型,在編譯後都會編程List。JVM看到的只是List,而由泛型附加的類型信息對JVM來說是不可見的。Java編譯器會在編譯時儘可能的發現可能出錯的地方,但是仍然無法避免在運行時刻出現類型轉換異常的情況。類型擦除也是Java的泛型實現方法與C++模版機制實現方式之間的重要區別。

可以通過兩個簡單的例子,來證明java泛型的類型擦除。

例1、

  1. public class Test4 {  
  2.     public static void main(String[] args) {  
  3.         ArrayList<String> arrayList1=new ArrayList<String>();  
  4.         arrayList1.add("abc");  
  5.         ArrayList<Integer> arrayList2=new ArrayList<Integer>();  
  6.         arrayList2.add(123);  
  7.         System.out.println(arrayList1.getClass()==arrayList2.getClass());  
  8.     }  
  9. }  

在這個例子中,我們定義了兩個ArrayList數組,不過一個是ArrayList<String>泛型類型,只能存儲字符串。一個是ArrayList<Integer>泛型類型,只能存儲整形。最後,我們通過arrayList1對象和arrayList2對象的getClass方法獲取它們的類的信息,最後發現結果爲true。說明泛型類型String和Integer都被擦除掉了,只剩下了原始類型


例2、

  1. public class Test4 {  
  2.     public static void main(String[] args) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {  
  3.         ArrayList<Integer> arrayList3=new ArrayList<Integer>();  
  4.         arrayList3.add(1);//這樣調用add方法只能存儲整形,因爲泛型類型的實例爲Integer  
  5.         arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, "asd");  
  6.         for (int i=0;i<arrayList3.size();i++) {  
  7.             System.out.println(arrayList3.get(i));  
  8.         }  
  9.     }  
在程序中定義了一個ArrayList泛型類型實例化爲Integer的對象,如果直接調用add方法,那麼只能存儲整形的數據。不過當我們利用反射調用add方法的時候,卻可以存儲字符串。這說明了Integer泛型實例在編譯之後被擦除了,只保留了原始類型


類型擦除帶來的問題請見原文:http://blog.csdn.net/wisgood/article/details/11762427



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