天天看點

java反射調用get/set方法,你還在拼接方法名嗎?

前言

最新工作中,遇到了通過反射調用get/set方法的地方,雖然反射的性能不是很好,但是相比較于寫死的不易擴充,getDeclareFields可以拿到所有的成員變量,後續添加或删除成員變量時,不用修改代碼,且應用次數隻在修改資料時使用,故犧牲一些性能提高擴充性

傳統的方式

見過很多人通過反射調用get/set方法都是通過擷取屬性的name,然後通過字元串截取将首字母大寫,再拼上get/set來做

還有稍微好一點的同學,通過fieldName轉成字元數組,首個字元-32來避免字元串截取的

誠然,我覺得兩種方式都可以,但是不知道有沒有遇到過,生成的get/set方法并不是已get/set開頭的,而是以is開頭的,比如boolean類型的成員變量。這個時候我們就需要去判斷屬性的類型,然後用不同的字首來拼接get/set方法名。其實,在jdk中已經包含了這樣的工具類

Introspector和PropertyDescriptor

關于這兩個類的詳細介紹,我這裡就不說了,簡單的了解就是對象資訊的描述,裡面提供了一些API友善我們拿到對象的資訊

java反射調用get/set方法,你還在拼接方法名嗎?
java反射調用get/set方法,你還在拼接方法名嗎?

PropertyDescriptor類提供了getReadMethod和getWriteMethod,其實就是對于get/set方法,至于方法名稱不需要我們來關于,這樣就可以避免方法名拼錯的情況了。

另外PropertyDescriptor除了可以通過Introspector擷取,也可以自己new來建立,其構造方法還是比較全的

java反射調用get/set方法,你還在拼接方法名嗎?

通常傳遞一個屬性的名稱和類對象class就可以了

java反射調用get/set方法,你還在拼接方法名嗎?
java反射調用get/set方法,你還在拼接方法名嗎?

通過上面兩種不同的實作方式可以看到,Introspector會額外有一個class屬性,但是類似serialVersionUID不會算在内;而自定義PropertyDescriptor需要通過反射拿到所有的屬性,雖然不會有class屬性,但是serialVersionUID會算在内,使用的時候需要注意一下。

如果你以為這就是Introspector的全部功能,那就大錯特錯了。Introspector不同于普通的反射,反射一次,一段時間内可重複使用,為什麼不是永久呢,看下源碼

java反射調用get/set方法,你還在拼接方法名嗎?
java反射調用get/set方法,你還在拼接方法名嗎?

注意中間加粗标紅的代碼,這裡除了同步之外,還做了一個本地的緩存

這個beanInfoCache

其實是一個WeakHashMap,每次gc被回收,是以上面說一段時間内可以重複使用而不是永久,也是為了避免OOM吧

總結

大概先說這麼多吧,雖然算不上什麼進階技術,但是能将工作中遇到的小問題解決也是成長啊!

為人:謙遜、激情、博學、審問、慎思、明辨、 笃行

學問:紙上得來終覺淺,絕知此事要躬行

為事:工欲善其事,必先利其器。

轉載請标注出處!