OkReflect: Java reflection framework

1. What is OkReflect?

OkReflect is a reflection of the Java package tool operation.

2. Why do I want to develop OkReflect?

In "Android componentized architecture" and "Android Development Guide plug of" two books, the authors are mentioned jOOR reflection framework. Just saw jOOR, I felt jOOR use and routine operations reflected a lot of elegant than up, but when I have it carried out some tests under different usage scenarios, but found some problems, so I do not think a better solution yet? After thought, I wrote OkReflect.

3. What is a reflection?

Java reflection mechanism allows the program at run time, for any class, are able to know all the properties and methods of this class. For any object, you can call any of its methods and properties. This method of function and dynamic invocation object information acquired dynamically called Java reflection mechanism.

1. Create a normal string

String str = "666";
复制代码

2. Use reflection to create a string

try {
    Class clazz = String.class;
    Constructor constructor = clazz.getConstructor(String.class);
    String instance = (String) constructor.newInstance("666");
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}
复制代码

So look, reflecting too much trouble, dim? But if you want to create a constructor instance is private, you can not tune, this time reflection comes in handy.

4. how to use reflection to invoke a private member?

Suppose we now have a Client class, its constructor and methods are private, this time we will be able to create this class through reflection, and call it private methods.

public class Client {

    private String name;

    private Client(String name) {
        this.name = name;
    }
  
    private void setName(String name) {
        this.name = name;
    }

}
复制代码
try {
    Class clazz = Class.forName("Client");
    Constructor constructor = clazz.getDeclaredConstructor(String.class);
    constructor.setAccessible(true);
    Client client = (Client) constructor.newInstance("小张");
    Method method = clazz.getDeclaredMethod("setName", String.class);
    method.setAccessible(true);
    method.invoke(client, "老王");
    System.out.println("");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}
复制代码

Create a class and a call to the effect is achieved, but this code looks too pretty, and do not be afraid, there jOOR.

5. What is jOOR?

1 Introduction

jOOR is a veteran reflector frame, it is encapsulated Java reflection operation.

2. Usage

String world = on("java.lang.String")  // 相当于 Class.forName()
                .create("Hello World") // 调用构造函数创建实例
                .call("substring", 6)  // 调用 substring 方法
                .get();                // 获取方法返回结果
复制代码

Very good, exceptions are gone, but you really can not directly use this, a problem or an exception will be reported. jOOR customized ReflectException, the exception will be encapsulated into reflection occurs ReflectException, so one packet or to try ... catch.

try {
    String world = on("java.lang.String")
            .create("Hello World")
            .call("substring", 6)
            .get();
} catch (ReflectException e) {
    // 处理异常
}
复制代码

While still have to pack a layer of try ... catch, but more than the most primitive reflex action is much better, but there is no better way to do it? The following process OkReflect look.

6. how is reflected by OkReflect?

try {
    String world = OkReflect.on("java.lang.String")
            .create("Hello World")
            .call("substring", 6)
            .get();
} catch (Exception e) {
    // 处理异常
}
复制代码

It seems with jOOR nothing different, ah, used to doing? Do not worry, OkReflect also allows you to handle exceptions in callbacks.

String world = OkReflect.on("java.lang.String")
                .create("Hello World")
                .call("substring", 6)
                .error(new OkReflect.OkReflectErrorCallback() {
                    @Override
                    public void onError(@NotNull Exception e) {
                        // 处理异常
                    }
                })
                .get();
复制代码

If you are using a Kotin language, then you can also write.

val world: String? = OkReflect.on("java.lang.String")
        .create("Hello World")
        .call("substring", 6)
        .error{
            // 处理异常
        }
        .get()
复制代码

7. OkReflect and jOOR of what is the difference?

1. Continuous call different methods

In jOOR, if you call a method that returns a value, a method that your next call will be to spend the value returned by a method call, when we do not care about the return value of the time, this will take the default action to some of the inconveniences. Suppose we now have a Manager class.

public class Manager {

    public List<String> items = new ArrayList<>();
    public int count;

    public int addData(String data) {
        this.items.add(data);
        count ++;
        return count;
    }

    public String getData(int i) {
        return items.get(i);
    }

}

复制代码

If we get used jOOR after adding data, after calling the method jOOR NoSuchMethodException throws an exception, because jOOR will be called getData method count addData return, and count is Integer, Integer indeed no getData method.

// jOOR
String data = on("Manager")
                .create()
                .call("addData", "data")
                .call("getData", 0)
                .get();
复制代码

If you use OkReflect for this action, it will not have this problem, because OkReflect default is to use an example to invoke the method.

// OkReflect
String data = OkReflect.on("Manager")
                .create()
                .call("addData", "data")
                .call("getData", 0)
                .get();
复制代码

How to do that if you want to ignore the return value after adding data, but to get that instance? You can only get the results returned values ​​in jOOR in, but in OkRefelct, you can use the getInstance method to get the instance instead of returning the results, such as the following that this

// OkReflect
Manager manager = OkReflect.on("Manager")
                    .create()
                    .call("addData", "data")
                    .getInstance();
复制代码

2. Type security

In jOOR, the type of return value acquisition is not guaranteed, the range is in use ReflectException try ... catch the words contained too young to be used to capture the Exception type conversion exception.

But in OkReflect, the type conversion when returning to capture anomalies, if the wrong type, it returns empty, this time you can use a null value to determine whether the conversion was successful, if you want it, you can be in ErrorCallback in the exception processing, for example such as the following.

String manager = OkReflect.on("Manager")
                .create()
                .call("addData", "data")
                .error(new OkReflect.OkReflectErrorCallback() {
                    @Override
                    public void onError(@NotNull Exception e) {
                        // 处理异常
                    }
                })
                .getInstance();
复制代码

3. Android final field

Field class is not in Android modifier field, which results in a final field to modify the conventional method is not feasible in Android. jOOR OkReflect and are modified by the modifier field reflected in the Field, but the system OkReflect judgment, and therefore may be modified OkReflect final field in Android.

4. The method of modifying or external call instance or field

jOOR the only method on the incoming class information, and OkReflect can be passed instance. This is what use is it? Such as Android in the Instrumentation, create an instance Hook himself is very troublesome, it is usually carried out with Hook Activity already Instrumentation. The following are examples of uses examples to invoke a method.

Client client = new Client();
OkReflect.on(client)
          .call("setName", "Alex")
          .get("name");
复制代码

8. how to configure OkReflect?

1. Gradle

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
复制代码
dependencies {
    implementation 'com.github.zeshaoaaa:OkReflect:master-SNAPSHOT'
}
复制代码

2. Maven

	<repositories>
		<repository>
		    <id>jitpack.io</id>
		    <url>https://jitpack.io</url>
		</repository>
	</repositories>
复制代码
	<dependency>
	    <groupId>com.github.zeshaoaaa</groupId>
	    <artifactId>OkReflect</artifactId>
	    <version>master-SNAPSHOT</version>
	</dependency>
复制代码

Guess you like

Origin juejin.im/post/5d24483f5188252ed917dd6d