寫在前面:學習插件化開發推薦書籍《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開發時的局限性,業界在使用反射開源框架都是基於基本反射語法自行封裝的框架。