java 反射 joor

在Java和Android中,我們常常會使用反射來達到一些兼容的目的。Java原生提供的反射很是麻煩,使用起來很是不方便。比如我們想要調UserManager的靜態方法get,使用原生的實現如下

1
2
3
4
5
6
7
8
9
10
11
try {
    final Method m = UserManager.class.getMethod("get", Context.class);
    m.setAccessible(true);
    m.invoke(null, this);
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

實現起來好不麻煩。這其中

  • 需要確定方法名和參數來獲取對應的Method對象
  • 設置Method對象的assessible爲true
  • 調用invoke方法,並且傳入對應的參數
  • 捕獲其中可能拋出來的一連串異常

那麼反射能簡單點麼,當然,而且還會簡單很多。

這就是本文想要介紹的,jOOR(Java Object Oriented Reflection),它是一個對java.lang.reflect包的簡單封裝,使得我們使用起來更加直接和方便。

使用jOOR,上面的代碼可以縮短成一行。

1
Reflect.on(UserManager.class).call("get", getApplicationContext());

依賴

API介紹

Reflect

  • Reflect.on 包裹一個類或者對象,表示在這個類或對象上進行反射,類的值可以使Class,也可以是完整的類名(包含包名信息)
  • Reflect.create 用來調用之前的類的構造方法,有兩種重載,一種有參數,一種無參數
  • Reflect.call 方法調用,傳入方法名和參數,如有返回值還需要調用get
  • Reflect.get 獲取(field和method返回)值相關,會進行類型轉換,常與call和field組合使用
  • Reflect.field 獲取屬性值相關,需要調用get獲取該值
  • Reflect.set 設置屬性相關。

ReflectException

引入ReflectException避免了我們去catch過多的異常,也減少了縱向代碼量,使得代碼簡潔不少。ReflectException拋出,可能是發生了以下異常。

  • ClassNotFoundException
  • IllegalAccessException
  • IllegalArgumentException
  • InstantiationException
  • InvocationTargetException
  • NoSuchMethodException
  • NoSuchFieldException
  • SecurityException

除此之外,ReflectException屬於unchecked 異常,語法上不需要顯式進行捕獲,但是也需要根據實際情況,斟酌是否進行顯式捕獲該異常。

使用示例

創建實例

1
String string = Reflect.on(String.class).create("Hello World").get();

訪問屬性(public,protected,package,private均可)

1
char pathSeparatorChar = Reflect.on(File.class).create("/sdcard/droidyue.com").field("pathSeparatorChar").get();

修改屬性(final屬性也可以修改)

1
String setValue = Reflect.on(File.class).create("/sdcard/drodiyue.com").set("path", "fakepath").get("path");

調用方法(public,protected,package,private均可)

1
2
3
4
ArrayList arrayList = new ArrayList();
arrayList.add("Hello");
arrayList.add("World");
int value = Reflect.on(arrayList).call("hugeCapacity", 12).get();

實現原理

Reflect實際是對原生java reflect進行封裝,屏蔽了無關細節。

以fields方法爲例,其內部實現可以看出是調用了java原生提供的反射相關的代碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public Map<String, Reflect> fields() {
    Map<String, Reflect> result = new LinkedHashMap<String, Reflect>();
    Class<?> type = type();

    do {
        for (Field field : type.getDeclaredFields()) {
            if (!isClass ^ Modifier.isStatic(field.getModifiers())) {
                String name = field.getName();

            if (!result.containsKey(name))
              result.put(name, field(name));
            }
        }

        type = type.getSuperclass();
    } while (type != null);

    return result;
}

庫地址

發佈了58 篇原創文章 · 獲贊 25 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章