1. 程式人生 > >泛型中的類型擦除

泛型中的類型擦除

泛型 add args 參數類型 一份 ack color div list

通過反射理解泛型的本質(類型擦除)

Java中的泛型是通過類型擦除來實現的。所謂類型擦除,是指通過類型參數合並,將泛型類型實例關聯到同一份字節碼上。編譯器只為泛型類型生成一份字節碼,並將其實例關聯到這份字節碼上。類型擦除的關鍵在於從泛型類型中清除類型參數的相關信息,並且再必要的時候添加類型檢查和類型轉換的方法。

下面通過兩個例子來證明在編譯時確實發生了類型擦除。

例1分別創建實際類型為String和Integer的ArrayList對象,通過getClass()方法獲取兩個實例的類,最後判斷這個實例的類是相等的,證明兩個實例共享同一個類。

// 聲明一個具體類型為String的ArrayList
ArrayList<String> arrayList1 = new ArrayList<String>(); arrayList1.add("abc"); // 聲明一個具體類型為Integer的ArrayList ArrayList<Integer> arrayList2 = new ArrayList<Integer>(); arrayList2.add(123); System.out.println(arrayList1.getClass() == arrayList2.getClass()); // 結果為true

例2創建一個只能存儲Integer的ArrayList對象,

      1、正常添加Integer

      2、使用Object.class 作為參數類型,利用反射添加 Integer , 利用反射添加 String

      3、以Integer.class 作為參數類型, 利用反射添加Integer , NoSuchMethodException

說明編譯後的泛型中只保留了 Object 作為參數類型,擦除了Integer 這個泛型信息。

說明泛型只是為了防止輸入出錯,只在編譯期有用,可以利用反射繞過編譯期。

    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList
<Integer> arrayList3 = new ArrayList<Integer>(); arrayList3.add(1); // arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, "一"); System .out.println("輸出一:"); for (int i = 0; i < arrayList3.size(); i++) { System.out.println(arrayList3.get(i)); // 輸出 } arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, 2); // 使用Object.class 可以add Integer arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, "二"); // 使用Object.class 可以add String System.out.println("輸出二:"); for (int i = 0; i < arrayList3.size(); i++) { System.out.println(arrayList3.get(i)); // 輸出 } System.out.println("輸出三:"); arrayList3.getClass().getMethod("add", Integer.class).invoke(arrayList3, 3); // 使用Integer.class NoSuchMethodException:java }


泛型中的類型擦除