Detailed explanation and application of reflection mechanism in Java

  • Share this:
post-title
The Java reflection mechanism is a powerful mechanism provided by the Java language, allowing programs to obtain information about objects (such as class names, properties, methods, etc.) at runtime. Through reflection, we can dynamically call an object's methods and access its properties, which greatly improves the flexibility and scalability of the code. For example, we can get the full name of the class through the `getClass () `method, and then get all the fields of the class through the `getDeclaredFields ()` method. Next, we can get all the methods of the class through the `getDeclaredMethod () `method. Finally, we can call these methods dynamically through the `invoke () `method.
In Java, the reflection mechanism is a powerful feature that allows us to check and manipulate the properties and methods of a class at runtime.

Through reflection, we can dynamically get the details of the class and call its methods or access its fields without knowing the specific information of these classes at compile time.

This feature makes reflection very useful in many scenarios, such as framework development, plug-in systems, dependency injection, etc.

What is reflection?.

Reflection means that when the program is running, the relevant information of the class (such as class name, attribute, method, etc.) can be obtained, and these methods can be called and accessed dynamically.

Reflection in Java is mainly through java.lang.reflectPackage to implement, the core class of which is ClassClass, which provides a rich API to manipulate the metadata of the class.

Gets the Class object of the class.

To use reflection, you first need to get the target class's ClassObject.

There are several common ways to obtain ClassObject: 1. # Get # directly through the class name:


   Class clazz = SomeClass.class;
   
2. # through the object's getClass()Method #:

   SomeClass obj = new SomeClass();
   Class clazz = obj.getClass();
   
3. # Load class # by fully qualified name:

   try {
       Class clazz = Class.forName("com.example.SomeClass");
   } catch (ClassNotFoundException e) {
       e.printStackTrace();
   }
   
Get the properties of the class.

Once there is ClassObject, you can get all fields of the class (including private fields).

Can be used getFields()Method to get public fields, or use getDeclaredFields()Method to get all fields (including private fields).


Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
    System.out.println("Field name: " + field.getName());
    // 设置可访问性以读取私有字段
    field.setAccessible(true);
    try {
        Object value = field.get(obj); // 获取字段值
        System.out.println("Field value: " + value);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

Get the method of the class.

Likewise, you can pass ClassThe object gets all the methods of the class.

Can be used getMethods()Method to obtain a public method, or use getDeclaredMethods()Method gets all methods (including private methods).


Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
    System.out.println("Method name: " + method.getName());
    // 设置可访问性以调用私有方法
    method.setAccessible(true);
    try {
        Object result = method.invoke(obj, args); // 调用方法并传递参数
        System.out.println("Method return value: " + result);
    } catch (IllegalAccessException | InvocationTargetException e) {
        e.printStackTrace();
    }
}

Dynamically call methods.

One of the most powerful aspects of reflection is the ability to dynamically call methods of objects at runtime.

The following is an example of how to call a method with parameters through reflection:


try {
    // 假设有一个方法名为sayHello,接受一个字符串参数
    Method method = clazz.getMethod("sayHello", String.class);
    Object result = method.invoke(obj, "World"); // 调用sayHello("World")
    System.out.println("Method return value: " + result);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
    e.printStackTrace();
}

Practical application case: Simple dependency injection framework.

In order to better understand the application of reflection, let's build a simple dependency injection framework.

This framework will automatically create objects and inject the required dependencies.


import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

public class SimpleDI {
    private Map instances = new HashMap<>();

    public void register(Class clazz) {
        try {
            instances.put(clazz.getName(), clazz.newInstance());
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public  T resolve(Class clazz) {
        return clazz.cast(instances.get(clazz.getName()));
    }
}

In the code above, SimpleDIThe class is responsible for managing instances of the class.

We use a HashMapTo store the mapping relationship between class names and instances.

registerMethod is used to register a class and create its instance, while resolveThe method returns the corresponding instance according to the class name.

Summarize.

The reflection mechanism in Java provides developers with great flexibility, allowing us to dynamically manipulate the structure and behavior of classes at runtime.

Although reflection may bring some performance overhead, it is an indispensable tool in many advanced application scenarios.

Through the introduction of this article, I hope you can better understand and use the reflection mechanism of Java, so as to write more flexible and powerful code.