前言

今天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已经修复了,链接在这里

Java-Reflection反射-获取包括父类在内的所有字段的更多相关文章

  1. java利用反射获取类的属性及类型

    java利用反射获取类的属性及类型. import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.Map ...

  2. java利用反射获取对象前后修改的内容(用于日志记录)

    import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Metho ...

  3. java 通过反射获取类属性结构,类方法,类父类及其泛型,类,接口和包

    首先自定义三个类 package reflection1; public interface MtInterface { void info(); } package reflection1; imp ...

  4. Java Reflection 反射基础

    反射基础: package reflection; /** * Created by : Infaraway * DATE : 2017/3/2 * Time : 23:06 * Funtion : ...

  5. java通过反射获取私有的构造方法,及反射擦除泛型数据类型约束

    /* * 反射获取私有的构造方法运行 * 不推荐,破坏了程序的安全性,封装性 * 暴力私有 */ public class ReflectDemo4 { public static void main ...

  6. java 通过反射获取调用类方法及属性

    首先说下反射是什么?反射是Sun公司推出的一组API,此组API位于Java.lang.reflect中 反射的作用是编写工具(例如eclipse),编写框架,当然对于一般的程序,我们不可能用反射来做 ...

  7. java通过反射获取调用变量以及方法

    一:反射概念 可以通过Class类获取某个类的成员变量以及方法,并且调用之. 二:通过反射获取方法.变量.构造方法 @Test // 通过反射获取类定义的方法 public void testMeth ...

  8. java通过反射获取Java对象属性值

    说明: 作为反射工具类,通过对象和属性的名字获取对象属性的值,如果在当前对象属性没有找到,依次向上收集所有父类的属 性,直到找到属性值,没有找到返回null: 代码: 1.classUtil pack ...

  9. java通过反射获取字段的类型

    import java.lang.reflect.Field;  //这是需要引入的包 Field[] f = 类名.class.getDeclaredFields(); //获取该类的字段for(F ...

随机推荐

  1. FPGA之初认识

    什么是FPGA FPGA(Field-Programmable Gate Array),即现场可编程门阵列 .看到编程两个字码农就笑了,不就是编程嘛,那可是我们的强项 .且慢,此编程非彼编程 .一定要 ...

  2. 分形在遥感和GIS中的应用

    GIS等高线化简 遥感图像的追踪 分形matlab实现:分形应用于遥感图像处理             低分辨率和高分辨率图形它们的形状是相似的(图像增强) 贪吃蛇和蚁群算法:试想管中窥豹,一只小蚂蚁 ...

  3. BUG 图片元素img下 高度超出 出现多余空白

    BUG 图片元素img下 高度超出 出现多余空白 1.将图片转换为块级对象 即,设置img为“display:block;”.   2.设置图片的垂直对齐方式 即设置图片的vertical-align ...

  4. hdu 4964 恶心模拟

    http://acm.hdu.edu.cn/showproblem.php?pid=4964 给定语句,按照语法翻译html并输出. 就是恶心的模拟,递归搞就行了 处理id和class时,在一个'&g ...

  5. POJ3046选蚂蚁创建集合_线性DP

    POJ3046选蚂蚁创建集合 一个人的精力是有限的呢,如果一直做一件事迟早会疲惫,所以自己要把握好,不要一直埋头于一件事,否则效率低下还浪费时间 题目大意:一共有T(1,2...n为其种类)种蚂蚁,A ...

  6. android TextView 设置部分文字背景色和文字颜色

    通过SpannableStringBuilder来实现,它就像html里边的元素改变指定文字的文字颜色或背景色 public class MainActivity extends Activity { ...

  7. [FAILED]Marking disk "DATA02" as an ASM disk

    执行删除asm磁盘时报错! [root@rac1 grid]# /etc/init.d/oracleasm deletedisk DATA01 /dev/sdc1 Marking disk " ...

  8. Java学习--数组与方法

    1. public class MethodDemo01{ public static void main(String args[]){ printInfo() ; // 调用printInfo() ...

  9. poj3253哈夫曼树

    Fence Repair Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java ...

  10. Android-Kotlin-函数表达式&String与Int转换$异常处理

    Kotlin的函数表达式: package cn.kotlin.kotlin_base03 /** * 函数第一种写法 */ fun addMethod1(number1: Int, number2: ...