Java-Reflection反射-獲取包括父類在內的所有字段


Java-Reflection反射-獲取包括父類在內的所有字段

前言

今天Android移動端要加個新功能,所以回歸Android程序員的身份.開發的過程中,發現了之前的代碼寫的有很多問題,真的應該把時間抽出來重構一下了.

其中有反射的一個坑,工具類某方法反射獲取傳入Model的屬性值.但是當我把公共屬性抽出來做基類的時候,發現獲取不到基類的屬性值了.原因是使用了getDeclaredFields();

分析

方法 功能
getFields() 獲取所有public字段,包括父類字段
getDeclaredFields() 獲取所有字段,public和protected和private,但是不包括父類字段

寫個小方法驗證一下下~

寫兩個類,里面定義三個字段,分別用public,protected,private修飾, 
一個叫ParentModel,作為父類. 
一個叫model,繼承ParentModel

/** * 用作父類 */ public class ParentModel { private String p_privateField; public String p_publicField; protected String p_protectedField; }

 

/** * 子類,繼承上面定義的用作父類的ParentModel */ public class Model extends ParentModel{ private String privateField; public String publicField; protected String protectedField; }

 

ok,分別使用getFields()和getDeclaredFields()獲取model的字段,循環打印出來.

 Field[] fs = Model.class.getFields(); Field[] fs1 = Model.class.getDeclaredFields(); for (Field f:fs) { Log.d("getFields","getFields---"+f.getName()); } for (Field f:fs1) { Log.d("getDeclaredFields","getDeclaredFields---"+f.getName()); }

 

見證答案的時候到了~ 
getFields()的打印輸出:

這里寫圖片描述

getDeclaredFields()的打印輸出:

這里寫圖片描述

測試證實了我們上面的結論是對的.

我想獲取子類和父類的所有Field

如果想用反射通過Model獲取parentModel和Model的所有字段,怎么辦?很明顯上面的兩個方法都是滿足不了的.那怎么辦?

不用怕,我們遞歸Model的父類去getDeclaredFields(),代碼如下:

List<Field> fieldList = new ArrayList<>() ; Class tempClass = Model.class; while (tempClass != null) {//當父類為null的時候說明到達了最上層的父類(Object類). fieldList.addAll(Arrays.asList(tempClass .getDeclaredFields())); tempClass = tempClass.getSuperclass(); //得到父類,然后賦給自己 } for (Field f : fieldList) { Log.d("getAllFields","getFields---"+f.getName()); }

 

這里寫圖片描述

可以看到我們獲取了Model和ParentModel的全部字段,不僅如此,還多出來了兩個字段shadow$_klass_ 和shadow_monitor_,這個是Object中的字段.

shadow$_monitor_shadow$_klass_是Android sdk21之后Object增加的兩個字段。

如果你想屏蔽Object類的影響,可以為while循環再添加一個條件:

while (tmpClass !=null && !tmpClass.getName().toLowerCase().equals("java.lang.object") ) { .... }

 

更新說明

2017.6.27更新:

之前被網友 lucky_god88 指出博客反射獲取的值和真實情況不符,核實之后,已經更正為正確答案,這里謝謝可愛的lucky_god88 發現並給我指出問題,解決問題的同時自己也在成長。同時也反省自己,以后要代碼多加驗證,謹慎細致,認真負責。

問題: 
1.getFields() 獲取到 protected 類型字段的值

這個原因至今沒有再次重現,很奇怪,很費解

2.getFields() 和 getDeclaredFields() 方法反射獲取多了一個字段$change

這個和開發工具的配置有關系,好像是因為開啟了Instant run 造成的,而且Android Studio 2.2.3已經修復了,鏈接在這里

參考資料

Retrieving the inherited attribute names/values using Java Reflection

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM