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已经修复了,链接在这里
Java-Reflection反射-获取包括父类在内的所有字段的更多相关文章
- java利用反射获取类的属性及类型
java利用反射获取类的属性及类型. import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.Map ...
- java利用反射获取对象前后修改的内容(用于日志记录)
import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Metho ...
- java 通过反射获取类属性结构,类方法,类父类及其泛型,类,接口和包
首先自定义三个类 package reflection1; public interface MtInterface { void info(); } package reflection1; imp ...
- Java Reflection 反射基础
反射基础: package reflection; /** * Created by : Infaraway * DATE : 2017/3/2 * Time : 23:06 * Funtion : ...
- java通过反射获取私有的构造方法,及反射擦除泛型数据类型约束
/* * 反射获取私有的构造方法运行 * 不推荐,破坏了程序的安全性,封装性 * 暴力私有 */ public class ReflectDemo4 { public static void main ...
- java 通过反射获取调用类方法及属性
首先说下反射是什么?反射是Sun公司推出的一组API,此组API位于Java.lang.reflect中 反射的作用是编写工具(例如eclipse),编写框架,当然对于一般的程序,我们不可能用反射来做 ...
- java通过反射获取调用变量以及方法
一:反射概念 可以通过Class类获取某个类的成员变量以及方法,并且调用之. 二:通过反射获取方法.变量.构造方法 @Test // 通过反射获取类定义的方法 public void testMeth ...
- java通过反射获取Java对象属性值
说明: 作为反射工具类,通过对象和属性的名字获取对象属性的值,如果在当前对象属性没有找到,依次向上收集所有父类的属 性,直到找到属性值,没有找到返回null: 代码: 1.classUtil pack ...
- java通过反射获取字段的类型
import java.lang.reflect.Field; //这是需要引入的包 Field[] f = 类名.class.getDeclaredFields(); //获取该类的字段for(F ...
随机推荐
- stm32常识
cmsis全称Cortex Microcontroller Software Interface Standard,就是Cortex微处理器软件接口标准 stm32每组gpio有7组端口,分别是2个3 ...
- codeforce864d
D. Make a Permutation! time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- centos下添加git
CentOS中yum里没有Git,需要手动安装. 首先需要安装git的依赖包 yum install curl yum install curl-devel yum install zlib-deve ...
- 分形之花篮(Flower Basket)
这一篇展示的图形与上一篇文章分形之皇冠(Crown)很相似. 核心代码: static void FractalFlowerBasket(const Vector3& vStart, cons ...
- nuget.org无法解析的办法
今天想学习ef框架,就着手安装最新的ef啦.可是遇到了问题,提示 未能解析此远程名称:'nuget.org' 就去上网找资料啦,发现原来是被墙了,表示无奈. 网上的资料提示,修改hosts文件或是dn ...
- consul集群docker版本脚本
https://blog.csdn.net/fenglailea/article/details/79098246 docker run -d --name node1 -e 'CONSUL_LOCA ...
- 利用CPaintDC::IntersectClipRect将绘图限制在局部区域
问题背景:画带坐标的图,例如 画里面那条曲线的时候,希望将绘图区域局限在坐标范围内,范围外的就自动屏蔽掉. 两个方案,一是用CPaintDC的SelectClipRgn函数,感觉略麻烦.另一个函数,就 ...
- kali linux 安装sublime text3完全教程
点击进入官网 下载页面 将鼠标放在64 bit(64位系统)上右击复制链接 打开终端: #wget 路径(粘贴刚复制的) #tar -xvvf 刚刚下载的文件文件名(解压) #mv 解压出来的文件名 ...
- SO_REUSEADDR SO_REUSEPORT
http://stackoverflow.com/questions/14388706/socket-options-so-reuseaddr-and-so-reuseport-how-do-they ...
- 初探日志框架Logback
一. 背景 最近因为学习项目时需要使用logback日志框架来打印日志, 使用过程中碰到很多的疑惑, 而且需要在控制台打印mybatis执行的sql语句, 于是决定沉下心来 研究一下logback的使 ...