Reflexión de Java (Reflection)

La reflexión de Java (Reflection) es una característica poderosa que permite a los programas consultar, acceder y modificar información sobre clases, interfaces, campos y métodos en tiempo de ejecución. La reflexión proporciona la capacidad de manipular clases dinámicamente, y es ampliamente utilizada en muchos frameworks y bibliotecas, como la inyección de dependencias del framework Spring.

API de reflexión

La API de reflexión de Java proporciona una serie de clases e interfaces para manipular objetos Class. Las clases principales incluyen:

  • java.lang.Class: Representa el objeto de la clase. Proporciona métodos para obtener los campos, métodos, constructores, etc. de la clase.
  • java.lang.reflect.Field: Representa los campos (atributos) de la clase. Proporciona la capacidad de acceder y modificar campos.
  • java.lang.reflect.Method: Representa los métodos de la clase. Proporciona la capacidad de invocar métodos.
  • java.lang.reflect.Constructor: Representa los constructores de la clase. Proporciona la capacidad de crear objetos.

Flujo de trabajo

  1. ObtenerClassObjeto: Primero, obtenga el objeto de la claseClassobjetivo.
  2. Obtener información de los miembrosObjetoClass: A través del
  3. objeto, se pueden obtener los campos, métodos, constructores, etc. de la clase.Operar sobre los miembros

: A través de la API de reflexión se pueden leer y modificar los valores de los campos, invocar métodos y crear objetos.

1. Obtener el objeto Class

1. Obtener el objeto Class

Cada clase tiene un objeto Class asociado en la JVM. El objeto Class se puede obtener de las siguientes maneras:

Class<?> clazz = String.class;

Mediante el literal de clase

String str = "Hello";
Class<?> clazz = str.getClass();

Mediante una instancia de objeto:

Class<?> clazz = Class.forName("java.lang.String");

2. Crear objetos

2. Crear objetos

Class<?> clazz = Class.forName("java.lang.String");
Object obj = clazz.getDeclaredConstructor().newInstance();

3. Acceder a los campos

3. Acceder a los campos

Class<?> clazz = Person.class;
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // 如果字段是私有的,需要设置为可访问
Object value = field.get(personInstance); // 获取字段值
field.set(personInstance, "New Name"); // 设置字段值

4. Invocar métodos

4. Invocar métodos

Class<?> clazz = Person.class;
Method method = clazz.getMethod("sayHello");
method.invoke(personInstance);

Method methodWithArgs = clazz.getMethod("greet", String.class);
methodWithArgs.invoke(personInstance, "World");

5. Obtener constructores

5. Obtener constructores

Class<?> clazz = Person.class;
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("John", 30);

6. Obtener interfaces y superclases

6. Obtener interfaces y superclases

Class<?> clazz = Person.class;

// 获取所有接口
Class<?>[] interfaces = clazz.getInterfaces();
for (Class<?> i : interfaces) {
    System.out.println("Interface: " + i.getName());
}

// 获取父类
Class<?> superClass = clazz.getSuperclass();
System.out.println("Superclass: " + superClass.getName());

Se pueden obtener mediante reflexión las interfaces implementadas por la clase y la superclase:

Ejemplo

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

public class ReflectionExample {

    public static void main(String[] args) throws Exception {
        Ejemplo
        Class<?> clazz = Person.class;
       
        // Obtener el objeto Class
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Object person = constructor.newInstance("John", 30);
       
        // Crear objeto
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true);
        System.out.println("Name: " + nameField.get(person));
       
        // Acceder al campo
        nameField.set(person, "Doe");
        System.out.println("Updated Name: " + nameField.get(person));
       
        // Modificar el campo
        Method greetMethod = clazz.getMethod("greet", String.class);
        greetMethod.invoke(person, "World");
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void greet(String message) {
        System.out.println(name + " says: " + message);
    }
}

// Invocar método

Name: John
Updated Name: Doe
Doe says: World

java.lang.reflect

java.lang.reflectCompila y ejecuta el código anterior, la salida es:

Es el paquete central del mecanismo de reflexión de Java y proporciona clases e interfaces para manipular clases y sus miembros (campos, métodos, constructores, etc.). A través de estas API, los desarrolladores pueden consultar y modificar dinámicamente la estructura de las clases en tiempo de ejecución.java.lang.reflectA continuación se presenta

1. ClassClase

  • la descripción detallada de las principales clases e interfaces del paquete:Funcionalidad
  • : Representa el objeto de la clase y proporciona métodos para obtener información de la clase, como campos, métodos, constructores, etc.:
    • getFields()Métodos principales
    • getDeclaredFields(): Obtiene todos los campos públicos.
    • getMethods(): Obtiene todos los campos declarados, incluidos los campos privados.
    • getDeclaredMethods(): Obtiene todos los métodos públicos.
    • getConstructors(): Obtiene todos los métodos declarados, incluidos los métodos privados.
    • getDeclaredConstructors(): Obtiene todos los constructores públicos.
    • getSuperclass(): Obtiene todos los constructores declarados, incluidos los constructores privados.
    • getInterfaces(): Obtiene la superclase de la clase.

2. FieldClase

  • : Obtiene todas las interfaces implementadas por la clase.Funcionalidad
  • : Representa los campos (atributos) de la clase y proporciona métodos para acceder y modificar los valores de los campos.:
    • get(Object obj)Métodos principales
    • set(Object obj, Object value): Obtiene el valor del campo del objeto especificado.
    • getType(): Establece el valor del campo del objeto especificado.
    • getModifiers(): Obtiene el tipo de datos del campo.

3. MethodClase

  • : Obtiene los modificadores del campo (como public, private).Funcionalidad
  • : Representa los métodos de la clase y proporciona la capacidad de invocar métodos.:
    • invoke(Object obj, Object... args)Métodos principales
    • getReturnType(): Invoca el método del objeto especificado.
    • getParameterTypes(): Obtiene el tipo de retorno del método.
    • getModifiers(): Obtiene los tipos de parámetros del método.

4. ConstructorClase

  • : Obtiene los modificadores del método (como public, private).Funcionalidad
  • : Representa los constructores de la clase y proporciona la capacidad de crear objetos.:
    • newInstance(Object... initargs)Métodos principales
    • getParameterTypes(): Crea una nueva instancia usando los parámetros del constructor especificados.
    • getModifiers(): Obtiene los tipos de parámetros del constructor.

Código de ejemplo

Código de ejemplojava.lang.reflectA continuación se muestra un ejemplo de uso del

Ejemplo

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

public class ReflectionExample {

    public static void main(String[] args) throws Exception {
        Ejemplo
        Class<?> clazz = Car.class;

        // Obtener el objeto Class
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Object car = constructor.newInstance("Toyota", 2020);

        // Crear el objeto Car
        Field modelField = clazz.getDeclaredField("model");
        Field yearField = clazz.getDeclaredField("year");
       
        // Acceder y modificar campos
        modelField.setAccessible(true);
        yearField.setAccessible(true);
       
        // Establecer el campo como accesible (si el campo es privado)
        System.out.println("Original Model: " + modelField.get(car));
        System.out.println("Original Year: " + yearField.get(car));
       
        // Imprimir el valor original del campo
        modelField.set(car, "Honda");
        yearField.set(car, 2024);
       
        // Modificar el valor del campo
        System.out.println("Updated Model: " + modelField.get(car));
        System.out.println("Updated Year: " + yearField.get(car));
       
        // Imprimir el valor del campo después de la modificación
        Method startMethod = clazz.getMethod("start");
        startMethod.invoke(car);
    }
}

class Car {
    private String model;
    private int year;

    public Car(String model, int year) {
        this.model = model;
        this.year = year;
    }

    public void start() {
        System.out.println("The " + model + " car of year " + year + " is starting.");
    }
}

// Invocar método

Original Model: Toyota
Original Year: 2020
Updated Model: Honda
Updated Year: 2024
The Honda car of year 2024 is starting.
Compila y ejecuta el código anterior, la salida es: