概述
为什么要写关于Java反射反面的博客呢,原因背景是这样的,最近我们team在使用retrofit做数据请求和解析,但是如果服务端返回的数据不包含某些数据的时候,解析出来的数据为null,就算在定义的时候,给model对象进行了一次最初的赋值也不行,原因在于解析的时候,没有数据的字段被retrofit解析成了null,这下可好了,调用这些模型的null字段就会跪掉,好了,测试bug来了,于是针对这个问题,我们程序狗们得着手解决啦。最直接最傻逼的做法当然就是去挨着每个字断去判断咯,但是我操,这个数据多的一逼,不瞒大家说,考虑到风险的问题,我们还真的这么干了,至少能够解决问题,我们处理这个事情的同事要吐血了,哈哈。现在过了发布,准备重构一下,那么我想到了两个办法去解决这个问题,得治标治本,从源头下手,有两个办法,一个是将恢复出来的模型进行解剖,如果发现字断为null的就赋值为空字符串,另一个办法是从解析入手,覆盖retrofit的解析方法,自定义解析规则,一个一个的来吧,首先从解剖入手呗,于是又了今天这篇博客。
Java反射基础
先来看看反射的定义吧:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
为了解决问题去学习是最好的学习方法。问题放在这里,但是发现对发射不熟悉怎么办呢,OK,google一下,找到oracle官网,先来看一番吧,照抄翻译网页的事咱就不干了,摘抄点精华吧。
Java Reflction可操纵成员Members
官网看到了Members包括:Fields、Methods和Constructors,其实也就是包含了最基本的一个对象的组成成分了。
Fields
获取Field的类型,一个属性可以是基本数据类型,也可以是引用类型,最基本的八种数据类型分别是boolean,byte,short,int,long,char,float和double,一个引用类型或者都直接或者间接继承自Object,或者是接口interface,或者是数组Array,或者是列表List或枚举等。
可以通过类全路径字符串描述或者对象的getClass方法来获取一个类。
好了现在我们就获得了Field。
这两个的区别在于,以一个List
获取描述符
对mods进行解析就可以知道描述符了。
操作对象的数据,这部分才是数据操作的核心。它可以将一个运行着的对象的数据进行改变,叼不叼。
既然获取到了一列Field,那么接下来只需要两个条件就行了,一个是对象,即对谁赋值,然后是值是多少。
以一个Student为例子。
假设又了一个Student对象student,那么进行赋值操作如下
好了,到这里,列的基本操作就完成啦。
Methods
Methods区域的过后补充。
Constructors
Constructors区域的过后补充。
解剖数据
现在回到文章一开始提出的需求,解剖一个对象,将空的字符串进行赋默认值操作,思路是采用的递归,直到所有的数据类型都是基本类型或者String类型作为结束,由于我们只关心String,那么开始吧。