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


欢迎关注个人微信公众号「浅浅同学的开发笔记」,最新的博客,好玩的事情,都会在上面分享,期待与你共同成长。

在这里插入图片描述

  • 12
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要通过Java反射获取类和子类的所有属性,我们可以使用Class类的getFields()和getDeclaredFields()方法。 - getFields()方法可以获取类中所有公共的(即用public修饰的)属性,包括类中的公共属性。返回的是一个数组,其中包含了所有公共属性的Field对象。 - getDeclaredFields()方法可以获取类中所有声明的属性,包括私有的、受保护的和默认访问权限的属性,但不包括类中的属性。返回的也是一个数组,其中包含了所有声明的属性的Field对象。 我们可以先获取子类的Class对象,然后利用getFields()和getDeclaredFields()方法获取子类自己声明的属性和从类继承的公共属性。 再获取类的Class对象,利用getFields()方法获取类的公共属性。 下面是一个示例代码: ```java import java.lang.reflect.Field; public class ReflectionExample { public static void main(String[] args) { Child child = new Child(); // 获取子类Class对象 Class<?> childClass = child.getClass(); // 获取子类自己声明的属性和从类继承的公共属性 Field[] childFields = childClass.getDeclaredFields(); for (Field field : childFields) { System.out.println(field.getName()); } // 获取类Class对象 Class<?> parentClass = childClass.getSuperclass(); // 获取类的公共属性 Field[] parentFields = parentClass.getFields(); for (Field field : parentFields) { System.out.println(field.getName()); } } } class Parent { public int parentField; } class Child extends Parent { private String childField; } ``` 在上面的示例中,我们创建了一个Parent类和一个Child类。Child类继承自Parent类,并在自己中声明了一个private的childField属性。 运行示例代码,结果会打印出子类和类的所有属性名: ``` childField parentField ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值