【小家java】爲什麼說Java中的泛型是“假”的?(通過反射繞過Java泛型)

相關閱讀

【小家java】java5新特性(簡述十大新特性) 重要一躍
【小家java】java6新特性(簡述十大新特性) 雞肋升級
【小家java】java7新特性(簡述八大新特性) 不溫不火
【小家java】java8新特性(簡述十大新特性) 飽受讚譽
【小家java】java9新特性(簡述十大新特性) 褒貶不一
【小家java】java10新特性(簡述十大新特性) 小步迭代


說在前面

泛型是JDK5帶給我們的新特性,雖然它處於歷史原因,有不完善的地方。但是更多的還是給與我們帶來方便的。下面先簡要先說說它的優點:

泛型就是參數化類型:

  • 適用於多種數據類型執行相同的代碼
  • 泛型中的類型在使用時指定
  • 泛型歸根到底就是“模版”

優點:使用泛型時,在實際使用之前類型就已經確定了,不需要強制類型轉換。提高安全性。
可以有:

  • 泛型類型
  • 泛型類
  • 泛型接口
  • 泛型方法
  • 泛型的繼承 extends/super
  • 泛型通配符

爲什麼說Java的泛型是”假”的呢?

其實Java爲了向下兼容,提出來的泛型只是一個語法糖,並不是像c++那樣是真的泛型。下面我通過兩個簡單的例子,可以讓大家感受一下:

   public static void main(String[] args) throws Exception {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        //list.add("a"); // 這樣直接添加肯定是不允許的

        //下面通過java的反射,繞過泛型  來給添加字符串
        Method add = list.getClass().getMethod("add", Object.class);
        add.invoke(list,"a");

        System.out.println(list); //[1, a] 輸出沒有沒問題
        System.out.println(list.get(1)); //a
    }

這裏面就證明了雖然List聲明爲只能裝Integer類型,但是我卻放進去了字符串類型,由此課件,泛型是“假”的,只存在於編譯期。再看一個例子:

  public static void main(String[] args) throws Exception {
        Map<String, String> map = new HashMap<>();
        String key = "key";
        Integer val = new Integer(1); //備註:此方法在Java9後標註爲過期了,建議使用valueOf,使用緩存來提高效率
        Method m = HashMap.class.getDeclaredMethod("put", new Class[]{Object.class, Object.class});
        m.invoke(map, key, val);

        System.out.println(map); //{key=1}
        //但是下面的輸出會報錯
        System.out.println(map.get(key)); // java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    }

此處需要注意了,雖然1放進去了。但是get出來的時候會報錯,因爲強轉失敗

最後

雖然java中的泛型是“假”的,會有泛型擦除的操作,但是不可否則,泛型的引入對java語言影響還是挺大的,讓它上升了一大步,所以本文借兩個例子,希望能夠加強讀者對java泛型更深的理解。

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