java反射:通過Method、Class發現泛型的本質

    在學習java集合的時候,泛型是個很重要的概念,它幫助我們防止了插入集合數據類型出錯。在學習java反射的過程中,我們通過集合類對象的類類型進行操作,那麼通過這種操作對集合泛型有什麼不同?
    首先我們創建兩個集合對象,其中一個帶有泛型String,另一個不帶有泛型,插入集合的元素類型不受限制

 ArrayList list=new ArrayList();
 ArrayList<String> list1=new ArrayList<String>();
     list1.add("hello");

    則我們現在可以向集合list中添加任意類型對象,而在list1中只能添加String類型的對象,如果我們向list1中加入Integer類型的數據對象,則在編譯階段會出現報錯
    接下來我們通過類類型和Method來調用ArrayList類中的方法

Class c1=list.getClass();
Class c2=list1.getClass();
System.out.println(c1==c2);

輸出結果爲:
true
    則兩個不同泛型的集合對象類型相同,這在我們看來是不合理的,爲什麼兩個不同泛型的對象的類型會相等呢?
    這是因爲,java的泛型是類型擦除的,即java的泛型在編譯階段是有效的,而在運行階段會把類型擦除,上述的兩個集合對象均變成ArrayList<>,此時比較其類型是相等的。而java的反射操作是在運行階段進行的,繞過了相應的編譯階段而轉換成了字節流,接下類我們來測試一下,java反射操作的執行階段:

 Method m=c2.getMethod("add", Object.class);
     m.invoke(list1, 20);
     System.out.println(list1.size());
     System.out.println(list1);

    通過集合的類類型進行方法的調用,這時我們向list1中插入一個int類型的數據,按照泛型的要求,這個操作會在編譯階段發生錯誤,而運行結果顯示:

2
[hello, 20]

    插入集合的操作成功進行,說明此時泛型已經被“擦除”,而反射操作在運行時期進行,由此我們可以得出結論:
    集合泛型在編譯階段有效,而在運行階段被“擦除”

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