Java反射給泛型集合賦值

柳先開 發表於 2022-01-14
Java

Java反射給泛型集合賦值

泛型

Java泛型簡單描述下:

比如建立一個List集合,我想在裡邊只放Student物件資訊,就需要寫成

List<Student> studentList = new ArrayList();

這個時候List裡面就只能放入Student型別的值,如果強行放入其他型別(比如說Integer)的就會提示錯誤資訊:

java.lang.ClassCastException: java.lang.Integer cannot be cast to com.entity.Student

按照這個結果來看,studentList裡面就只能放入Student型別的值,沒有什麼問題。

然後,奇怪的事情發生了,在公司專案的log裡發現了一個error:

java.lang.ClassCastException: java.lang.Integer cannot be cast to com.entity.Student

原始碼類似於:

Student student = studentList.get(0);

What? 集合建立的時候明明給的泛型是Student啊,這個String是哪蹦出來的。

這個時候又得提出一個概念:

反射

比較全面的解釋:

JAVA反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。
要想解剖一個類,必須先要獲取到該類的位元組碼檔案物件。而解剖使用的就是Class類中的方法.所以先要獲取到每一個位元組碼檔案對應的Class型別的物件.

一通debug,我發現了這麼一段程式碼(來自於hutools包內的某個方法中,詳細是哪個記不太清了,模仿著寫寫):

    public List testReflect(Object arg[], List list) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<? extends List> aClass = list.getClass();
        Method method = aClass.getMethod("add", Object.class);
        for (Object o : arg) {
            method.invoke(list, o);
        }
        return list;
    }

差不多就這樣子,入參是[1,2,3,4]和studentList,在外邊取list中的值時,發現:

java.lang.ClassCastException: java.lang.Integer cannot be cast to com.entity.Student

這玩意,利用反射獲取了List的add方法,值型別也不判斷,直接給塞進集合裡了。。。。

其實剛開始碰到時,一臉懵的,耗費了很長時間取排查問題,我泛型Student的List,怎麼會出現這種問題,從List中取出來的值不能轉換成Student。。。。

不過後來發現原因之後,感覺其實也不復雜,挺簡單的,還是經驗太少,判斷錯誤能力不行,共勉。

上面的程式碼用的Student類和String、Integer代替,公司內部程式碼就不透露了。