写在前面:学习插件化开发推荐书籍《Android 插件化开发指南》,本系列博客所整理知识部分内容出自此书。
在之前的项目架构的博文中,我们提到了项目插件化架构,提到插件化架构不得不提的到Java中最强大的技术 —— Java 反射技术,反射技术基本是贯穿整个插件化最核心的基础技术,下图是本人整理的插件化在理解时需要了解或者学习的知识点:
本文我们先着重讲一下Java反射技术。
一、基本反射技术
反射包括以下技术:
1. 根据一个字符串得到一个类的对象。
2. 获取一个类的所有公有或者私有、静态或实例的字段、方法、属性。
3. 对泛型类的反射。
1.1 根据一个字符串得到一个类
a). getClass
通过一个对象,获取它的类型。类型用Class表示,例如:
String str = "abc";
Class c1 = str.getClass();
b). Class.forName
这个方法用的最多。
通过一个字符串获取一个类型。这个字符串由类的命名空间和类的名称组成。而通过getSuperClass方法,获取对象的父类型。例如:
try { Class c2 = Class.forName("java.lang.String"); Class c3 = Class.forName("android.widget.Button"); // 通过getSuperClass获取父类类型,每个函数都有这个函数 Class c4 = c3.getSuperClass(); } catch(ClassNotFoundException e) { e.printStackTrace(); }
c). Class 属性
每个类都有 class 属性,可以得到这个类的类型。例如:
Class c2 = String.class; Class c3 = int.class;
d). TYPE 属性
基本类型,如BOOLEAN,都有TYPE属性,可以得到这个基本类型的类型:
Class c2 = Boolean.TYPE;
Class c3 = Short.TYPE;
1.2 获取类的成员
a). 获取类的构造函数
获取类的构造函数,包括private和public两种,支持无参数和有参数这两种类型的构造函数。下面是获取类构造函数的方式:
- 获取类的所有构造函数:通过Class.getDeclaredConstructors方法可以获取类的所有构造函数,包括public和private的构造函数,我们可以通过for循环遍历每一个构造函数。
- 获取类的某个构造函数:通过Class.getDeclaredConstructor方法。
反射到类的构造函数很重要,因为反射技术的流程为:通过字符串反射出一个类,然后通过反射获取到类的构造函数,执行构造函数后就得到了这个类的实例,有了这个实例就可以通过反射进一步得到实例的所有字段和方法。通过反射调用构造函数得到类的实例,这要借助Constructor的newInstance方法。
b). 获取类的实例和方法并进行调用或者修改
在通过反射构造函数获取到类的对象后,我们可以执行以下操作:
- 获取类的私有实例并调用。
- 获取类的静态私有方法并调用。
- 获取类的私有字段并修改。
- 获取类的私有静态字段并修改。
1.3 对泛型类反射
Android 源码系统中存在大量泛型,所以插件化技术离不开对泛型进行反射,比如单例模式。
二、反射开源库 jOOR
调用Java提供的基本的反射语法,写出来的代码会非常艰涩。这里我们推荐一个相对自然、简单、面向对象的开源库 —— jOOR 库。
jOOR库只有两个类,Reflect.java 和 ReflectException.java,导入这个库不需要依赖gradle,可以直接将这两个类拖到项目中即可。
Reflect.java为核心类,包含以下5个核心方法:
- on:包裹一个类或者对象,表示在此类或对象上进行反射。
- create:调用构造方法。
- call:方法调用,传入方法名和参数。
- get:获取(field和method返回)值相关,会进行类型转换,常与call组合。
- set:设置属性值。
jOOR 虽然很强大,但是在Android领域使用时会存在一定的局限性,因为在Android系统中不支持反射final类型的字段。
jOOR 库 github 地址:https://github.com/jOOQ/jOOR 。
因为jOOR在Android开发时的局限性,业界在使用反射开源框架都是基于基本反射语法自行封装的框架。