Advanced Java - Reflection Mechanism

What is the reflection mechanism?

Java's reflection mechanism refers to the ability to dynamically obtain class information and manipulate its members (fields, methods, constructors, etc.) at runtime. Through reflection, you can dynamically create objects, call methods, access or modify fields when the program is running, without the need to determine these operations at compile time.

Static compilation and dynamic compilation

  1. Static compilation is to determine the type and bind the object at compile time;
  2. Dynamic compilation is to determine the type and bind the object at runtime.

Advantages and disadvantages of reflection mechanism

  1. Advantages: It can judge the runtime type and dynamically load classes to improve the flexibility of the code.
  2. Disadvantages: There will be a performance bottleneck, because reflection is equivalent to a series of interpretation operations, informing the JVM of what to do, and the performance is much slower than direct Java code.

Application Scenarios of Reflection Mechanism

Reflection is the core principle of many framework designs. Through functions such as obtaining class information, calling methods, and creating objects at runtime, the flexibility and scalability of the framework are realized. Although reflection is not often used directly in daily project development, reflection mechanisms are widely used in modular development, dynamic proxy design patterns, and some frameworks (such as Spring and Hibernate).

for example,

  1. When JDBC connects to the database, use Class.forName() to load the driver of the database through reflection. This is because when writing code, we cannot predetermine the specific database driver class to be used, but obtain the name of the driver class to be used according to the configuration file or other methods, and then use the reflection mechanism to dynamically load and initialize the class to achieve Database Connectivity.
  2. The Spring framework implements the process of loading beans in the XML configuration mode through the reflection mechanism. Spring loads all XML or Properties configuration files in the program into memory, and then parses the contents, including obtaining the bytecode string of the entity class and related attribute information. Next, use the reflection mechanism to obtain the corresponding Class instance according to the bytecode string, and then dynamically create the object and configure its properties.

These examples show the application of the reflection mechanism in actual development, so that we can dynamically load classes at runtime, obtain class information and perform corresponding operations, which enhances the flexibility and scalability of the code. The application of reflection is far more than that, and it can be found in many frameworks, libraries, and some general tool classes.

It should be noted that although the reflection mechanism provides great flexibility, excessive use of reflection may reduce the readability and performance of the code, and also need to pay attention to security and permission control issues. Therefore, it is necessary to carefully weigh the pros and cons when using reflection, and apply it reasonably according to specific needs.

Reflection related classes

The Java reflection mechanism is mainly implemented using the classes and interfaces in the java.lang.reflect package. Here are some of the main reflection related classes:

  1. Class class: Represents a class or interface, through which class information can be obtained at runtime, such as class name, modifier, parent class, interface, field, method, etc.
  2. Constructor class: represents the construction method of the class. You can obtain all public or all construction methods through the getConstructors() or getDeclaredConstructors() method of the Class object, and then use the newInstance() method to create the object.
  3. Field class: represents the field of the class. You can get all public or all fields through the getFields() or getDeclaredFields() method of the Class object, and then use the get() and set() methods to read or modify the field values.
  4. Method class: represents the method of the class. You can get all public or all methods through the getMethods() or getDeclaredMethods() method of the Class object, and then call the method through the invoke() method.

Through reflection, you can dynamically obtain class information and manipulate objects flexibly, but since reflection involves dynamic analysis and type checking, it will bring a certain performance loss, and in unnecessary cases, you should try to avoid excessive use reflection mechanism.

Methods commonly used in reflection

  • Get class object:
  1. Class.forName(String className): Get the corresponding class object according to the class name.
  2. obj.getClass(): Get the class object to which the object belongs.
  • Get class information:
  1. getFields(): Get the public fields of the class (including inherited public fields).
  2. getDeclaredFields(): Gets all fields declared by the class (excluding inherited fields).
  3. getMethods(): Get the public methods of the class (including inherited public methods).
  4. getDeclaredMethods(): Gets all methods declared by the class (excluding inherited methods).
  5. getConstructors(): Gets all public constructors of the class.
  6. getDeclaredConstructors(): Gets all constructors declared by the class.
  • Instantiation of the action class:
  1. newInstance(): Creates an instance of a class using the default constructor.
  • Call method:
  1. invoke(Object obj, Object... args): Invoke the method on the specified object.
  2. getMethod(String name, Class<?>... parameterTypes): Get the public method with the specified name and parameter types.
  3. getDeclaredMethod(String name, Class<?>... parameterTypes): Get the method with the specified name and parameter type.
  • Access fields:
  1. get(Object obj): Get the field value on the specified object.
  2. set(Object obj, Object value): Sets the field value on the specified object.
  3. getField(String name): Get the public field with the specified name.
  4. getDeclaredField(String name): Get the field with the specified name.

It should be noted that the use of reflection should be cautious, and in scenarios with high performance requirements, it is recommended to use ordinary method calls.

Three common ways to get reflection in Java

  1. Realize the reflection mechanism through the new object: first create the instance object of the class, then use the getClass() method of the instance object to obtain the class object, and then obtain related information and operations through the class object.
    MyClass obj = new MyClass();
    Class clazz = obj.getClass();
    // 获取属性、方法等信息
    
  2. Realize the reflection mechanism through the path: pass the fully qualified name of the class (package name + class name) as a string into the Class.forName() method to obtain the class object.
    MyClass obj = new MyClass();
    Class clazz = obj.getClass();
    // 获取属性、方法等信息
    
  3. Realize the reflection mechanism through the class name: directly use the class literal constant to obtain the class object.
    Class clazz = MyClass.class;
    // 获取属性、方法等信息
    

example

Here is a simple sample code using reflection

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Main {

    public static void main(String[] args) {
        try {
            // 获取类对象
            Class<?> clazz = MyClass.class;

            // 获取类的公共字段
            Field[] fields = clazz.getFields();
            System.out.println("公共字段:");
            for (Field field : fields) {
                System.out.println(field.getName());
            }

            System.out.println();

            // 获取类的所有方法
            Method[] methods = clazz.getDeclaredMethods();
            System.out.println("所有方法:");
            for (Method method : methods) {
                System.out.println(method.getName());
            }

            System.out.println();

            // 创建类的实例
            Object obj = clazz.newInstance();

            // 调用方法
            Method method = clazz.getMethod("printMessage", String.class);
            method.invoke(obj, "Hello, reflection!");

            System.out.println();

            // 访问字段
            Field field = clazz.getDeclaredField("message");
            field.setAccessible(true); // 设置可访问私有字段
            String message = (String) field.get(obj);
            System.out.println("字段值:" + message);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MyClass {
    public String message;

    public void printMessage(String msg) {
        System.out.println(msg);
    }
}

The above sample code demonstrates how to obtain the field and method information of the class through reflection, create an object instance and call the method, and access the field value of the object. Note that when accessing a private field, you need to use setAccessible(true) to set the field to be accessible. The example output is as follows:

公共字段:
message

所有方法:
printMessage

Hello, reflection!

字段值:null

Guess you like

Origin blog.csdn.net/m0_74293254/article/details/132476926