Foreword
反射的作用我在这就不多说了,每次用到反射都是那么一坨代码丢进去,总是让人觉得很不优雅,如今有了我这个反射工具类,那么大家就可以一句话优雅地来完成反射的工作,该工具类是站在 jOOR 的肩膀上进行改造,修复了它没有完成的工作,至于修复了什么,后面源码分析会详述,至于这个工具类在哪,现已加入至 1.12.0 版本的 AndroidUtilCode,下面来介绍下其功能。
Functions
其 APIs 如下所示:
反射相关 -> ReflectUtils.java -> Test
1 | reflect : 设置要反射的类 |
Use
实例化反射对象
比如,我们实例化一个 String
对象可以这样做:
1 | String str1 = ReflectUtils.reflect(String.class).newInstance().get(); |
设置反射的方法
比如,我们想要调用 String
的 substring
函数可以这样做:
1 | String str1 = ReflectUtils.reflect((Object) "1234").method("substring", 2).get(); |
设置反射的字段
比如,TestPrivateStaticFinal.java
如下所示:
1 | public class TestPrivateStaticFinal { |
我们要设置其 I1
、I2
值为 2,可以如下操作:
1 | ReflectUtils.reflect(TestPrivateStaticFinal.class).field("I1", 2); |
要获取其 I1
、I2
值的话,可以如下操作:
1 | ReflectUtils.reflect(TestPrivateStaticFinal.class).field("I1").get() |
当然,字段操作也有更高级的操作,比如 Test1.java
测试类如下所示:
1 | public class Test1 { |
我对其进行的单元测试如下所示:
1 |
|
根据如上注释相信大家也可以理解一二了,如果还想了解更多使用方式,可以查看我写的单元测试类 ReflectUtilsTest,其使用方式就介绍到这里,下面介绍其实现方式。
Achieve
实现的话是站在 jOOR 的肩膀上进行改造,其内部封装了一个 private final Object object;
变量,每次进行反射操作时都会重新实例化一个变量并把结果赋予该变量,最终 get()
就是获取其值,比如我们来看一下 newInstance
的操作,其涉及的代码如下所示:
1 | /** |
jOOR 所没有做到的就是没有对多个符合的 Constructor
进行排序,而是直接返回了第一个与之匹配的。这样说有点抽象,我举个例子应该就明白了,比如说有两个构造函数如下所示:
1 | public class Test { |
jOOR 反射调用构造函数参数传入 Long
类型,很可能就会走 Test(Object n)
这个构造函数,而我修改过后就是对多个符合的 Constructor
进行排序,匹配出与之最接近的父类,也就是会走 Test(Number n)
这个构造函数,同理,在后面的 method
中的参数匹配 jOOR 也是存在这个问题,我也已经对其修复了。
还有就是 jOOR 对 private static final
字段先 get
再 set
会报异常 java.lang.IllegalAccessException
异常,是因为对 private static final
字段 get
的时候没有去除 final
属性,如果在 get
时就把 final
去掉即可解决,那样在 set
的时候就不会报错。然而,在 Android 的 SDK 中是没有 Field.class.getDeclaredField("modifiers")
这个字段的,所以会报 NoSuchFieldException
异常,这方面我做了容错处理,相关代码如下所示:
1 | /** |
所以该工具类既完美支持 Java,也完美支持 Android。
Conclusion
好了,这次反射工具类就介绍到这了,是不是觉得如斯优雅,如果觉得好的话以后遇到反射的问题,那就快用我这个工具类吧,这么好的东西藏着不用真的是可惜了哦。
关于安卓核心常用工具类我已经差不多都封装了,今后应该也不会在核心的里面新增了,除非确实很需要我才会再新增某个工具类,其余不常用的我都会放在 subutil 中,感谢大家一直陪伴着 AndroidUtilCode 的成长。