getDeclaredFields()-Reflection反射-获取包括父类在内的所有字段

本文主要是介绍getDeclaredFields()-Reflection反射-获取包括父类在内的所有字段,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

今天Android移动端要加个新功能,所以回归Android程序员的身份.开发的过程中,发现了之前的代码写的有很多问题,真的应该把时间抽出来重构一下了.

其中有反射的一个坑,工具类某方法反射获取传入Model的属性值.但是当我把公共属性抽出来做基类的时候,发现获取不到基类的属性值了.原因是使用了getDeclaredFields();

分析

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

写个小方法验证一下下~

写两个类,里面定义三个字段,分别用public,protected,private修饰, 
一个叫ParentModel,作为父类. 
一个叫model,继承ParentModel

 
  1. /**

  2. * 用作父类

  3. */

  4. public class ParentModel {

  5.  
  6. private String p_privateField;

  7. public String p_publicField;

  8. protected String p_protectedField;

  9. }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
 
  1. /**

  2. * 子类,继承上面定义的用作父类的ParentModel

  3. */

  4. public class Model extends ParentModel{

  5.  
  6. private String privateField;

  7. public String publicField;

  8. protected String protectedField;

  9.  
  10. }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

ok,分别使用getFields()和getDeclaredFields()获取model的字段,循环打印出来.

 
  1. Field[] fs = Model.class.getFields();

  2. Field[] fs1 = Model.class.getDeclaredFields();

  3. for (Field f:fs) {

  4. Log.d("getFields","getFields---"+f.getName());

  5. }

  6.  
  7. for (Field f:fs1) {

  8. Log.d("getDeclaredFields","getDeclaredFields---"+f.getName());

  9. }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

见证答案的时候到了~ 
getFields()的打印输出:

这里写图片描述

getDeclaredFields()的打印输出:

这里写图片描述

测试证实了我们上面的结论是对的.

我想获取子类和父类的所有Field

如果想用反射通过Model获取parentModel和Model的所有字段,怎么办?很明显上面的两个方法都是满足不了的.那怎么办?

不用怕,我们递归Model的父类去getDeclaredFields(),代码如下:

 
  1. List<Field> fieldList = new ArrayList<>() ;

  2. Class tempClass = Model.class;

  3. while (tempClass != null) {//当父类为null的时候说明到达了最上层的父类(Object类).

  4. fieldList.addAll(Arrays.asList(tempClass .getDeclaredFields()));

  5. tempClass = tempClass.getSuperclass(); //得到父类,然后赋给自己

  6. }

  7. for (Field f : fieldList) {

  8.  
  9. Log.d("getAllFields","getFields---"+f.getName());

  10. }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里写图片描述

可以看到我们获取了Model和ParentModel的全部字段,不仅如此,还多出来了两个字段shadow$_klass_ 和shadow_monitor_,这个是Object中的字段.

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

如果你想屏蔽Object类的影响,可以为while循环再添加一个条件:

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

  2. {

  3. ....

  4. }

  • 1
  • 2
  • 3
  • 4

更新说明

2017.6.27更新:

之前被网友 lucky_god88 指出博客反射获取的值和真实情况不符,核实之后,已经更正为正确答案,这里谢谢可爱的lucky_god88 发现并给我指出问题,解决问题的同时自己也在成长。同时也反省自己,以后要代码多加验证,谨慎细致,认真负责。

问题: 
1.getFields() 获取到 protected 类型字段的值

这个原因至今没有再次重现,很奇怪,很费解

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

这个和开发工具的配置有关系,好像是因为开启了Instant run 造成的,而且Android Studio 2.2.3已经修复了,链接在这里

如果方法是 private修饰的,当你用反射去访问的时候setAccessible(true); 之后 才能访问

参考资料

Retrieving the inherited attribute names/values using Java Reflection

这篇关于getDeclaredFields()-Reflection反射-获取包括父类在内的所有字段的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/710210

相关文章

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下:

golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法

《golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法》:本文主要介绍golang获取当前时间、时间戳和时间字符串及它们之间的相互转换,本文通过实例代码给大家介绍的非常详细,感兴趣... 目录1、获取当前时间2、获取当前时间戳3、获取当前时间的字符串格式4、它们之间的相互转化上篇文章给大家介

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

微信公众号脚本-获取热搜自动新建草稿并发布文章

《微信公众号脚本-获取热搜自动新建草稿并发布文章》本来想写一个自动化发布微信公众号的小绿书的脚本,但是微信公众号官网没有小绿书的接口,那就写一个获取热搜微信普通文章的脚本吧,:本文主要介绍微信公众... 目录介绍思路前期准备环境要求获取接口token获取热搜获取热搜数据下载热搜图片给图片加上标题文字上传图片

java中反射(Reflection)机制举例详解

《java中反射(Reflection)机制举例详解》Java中的反射机制是指Java程序在运行期间可以获取到一个对象的全部信息,:本文主要介绍java中反射(Reflection)机制的相关资料... 目录一、什么是反射?二、反射的用途三、获取Class对象四、Class类型的对象使用场景1五、Class

使用Python实现获取网页指定内容

《使用Python实现获取网页指定内容》在当今互联网时代,网页数据抓取是一项非常重要的技能,本文将带你从零开始学习如何使用Python获取网页中的指定内容,希望对大家有所帮助... 目录引言1. 网页抓取的基本概念2. python中的网页抓取库3. 安装必要的库4. 发送HTTP请求并获取网页内容5. 解

Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到... python将mysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件