一個朋友圈泛型問題引起的「案子」

昨天朋友圈問了一個問題:
對於下面的list,何如在list添加一個Integer型整數?java

ArrayList<String> list = new ArrayList<String>();複製代碼

有這樣幾種回答:bash

  • 1.不知道(非專業回答)
  • 2.硬塞(非專業回答)
  • 3.把String 改爲Integer再添加(違背了問題初衷)
  • 4.把String改爲Object,能夠加任意類型(違背了問題初衷)
  • 5.String換成通配符
  • 6.反射

對於一、2就不說了,屬於搞事情的!三、四、5三種方式違背了問題的初衷,若是能夠改,那咱們直接new三個ArrayList就能夠了。6反射,這個是無限接近的,那麼這個和反射有什麼關係呢?下來看下下面幾個例子:spa

public static void main(String[] args) {

        ArrayList list=new ArrayList();

        ArrayList<String> str_list=new ArrayList<String>();

        ArrayList<Integer> int_list=new ArrayList<Integer>();

        ArrayList<Object> obj_list=new ArrayList<Object>();
        //對象比較
        System.out.println(list == str_list);
        System.out.println(list == int_list);
        System.out.println(list == obj_list);

        //對象的運行時class比較
        System.out.println(list.getClass() == str_list.getClass());
        System.out.println(list.getClass() == int_list.getClass());
        System.out.println(list.getClass() == obj_list.getClass());
    }複製代碼

結果:code

false
false
false
true
true
true複製代碼

其實上面三個很容易理解,不一樣對象在內存中的地址確定是不一樣的,所以均爲false;下面三個均爲true?是的,確實爲true,這就引出了朋友圈的那個問題。爲何不一樣的三個對象,他們的getClass是同樣的,不該該是有三個不一樣的hashCode嗎?這個其實就是泛型編譯時和運行時的問題
對於泛型來講,泛型只在編譯階段有效,編譯以後,集合的泛型是去泛型化的;緣由:因爲JVM泛型的擦除機制,在運行時JVM是不知道泛型信息的
所以:java集合中的泛型,是來約束用戶的錯誤輸入的,只在編譯時有效;
在回到問題最初,咱們怎麼才能將一個Integer對像放入上面定義的list中呢?既然集合中的泛型是編譯時有效的,那我咱們就能夠經過繞過編譯的方式進行插入。那麼如何繞過編譯時的校驗呢?答案就是用反射;咱們知道JAVA反射機制是指:
「在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制。
OK,再來看程序:對象

ArrayList<String> str_list=new ArrayList<String>();
        //獲取類信息
        Class c=str_list.getClass();
        //獲取add方法
        Method m=c.getMethod("add", Object.class);
        //運行時調用add方法
        m.invoke(str_list, 20);
        //輸出當前str_list
        System.out.println(str_list);複製代碼

結果:內存

[20]複製代碼

從結果能夠看出,咱們完成了在list中添加Integer的任務。
【泛型、反射、編譯時、運行時】
你們週末愉快!get

相關文章
相關標籤/搜索