Рефлексия Java

Рефлексия Java — это мощная функция, которая позволяет программам запрашивать, получать доступ и изменять информацию о классах, интерфейсах, полях и методах во время выполнения. Рефлексия предоставляет возможность динамически манипулировать классами, что широко используется во многих фреймворках и библиотеках, таких как внедрение зависимостей в фреймворке Spring.

API рефлексии

API рефлексии Java предоставляет ряд классов и интерфейсов для манипулирования объектами Class. Основные классы включают:

  • java.lang.Class: Представляет объект класса. Предоставляет методы для получения полей, методов, конструкторов класса и т. д.
  • java.lang.reflect.Field: Представляет поля (атрибуты) класса. Предоставляет возможность получать доступ к полям и изменять их.
  • java.lang.reflect.Method: Представляет методы класса. Предоставляет возможность вызова методов.
  • java.lang.reflect.Constructor: Представляет конструкторы класса. Предоставляет возможность создания объектов.

Рабочий процесс

  1. ПолучитьClassObject: Сначала получите объект целевого классаClassобъект.
  2. Получение информации о членах: ЧерезClassобъект, вы можете получить информацию о полях, методах, конструкторах класса и т. д.
  3. Манипулирование членами: Через API отражения вы можете читать и изменять значения полей, вызывать методы и создавать объекты.

Ниже приведены основные способы использования отражения Java и их типичные применения.

1. Получение объекта Class

У каждого класса есть связанный объект Class в JVM. Вы можете получить объект Class следующими способами:

С помощью литералов класса

Class<?> clazz = String.class;

Через экземпляр объекта:

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

С помощью метода Class.forName():

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

2. Создание объектов

Вы можете использовать рефлексию для динамического создания объектов:

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

3. Доступ к полям

Вы можете получать доступ к полям класса и изменять их с помощью рефлексии:

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

4. Вызов методов

Вы можете вызывать методы класса с помощью рефлексии:

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

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

5. Получение конструкторов

Вы можете использовать рефлексию для получения и вызова конструкторов:

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

6. Получение интерфейсов и родительских классов

Вы можете использовать рефлексию, чтобы получить интерфейсы, реализуемые классом, и его родительский класс:

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());

Ниже приведён полный пример, показывающий, как использовать рефлексию для создания объектов, доступа к полям и вызова методов:

Пример

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 {
        // Получить объект Class
        Class<?> clazz = Person.class;
       
        // Создать объект
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Object person = constructor.newInstance("John", 30);
       
        // Доступ к полям
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true);
        System.out.println("Имя: " + nameField.get(person));
       
        // Изменить поля
        nameField.set(person, "Доу");
        System.out.println("Обновлённое имя: " + nameField.get(person));
       
        // Вызвать методы
        Method greetMethod = clazz.getMethod("greet", String.класс);
        greetMethod.invoke(person, "Мир");
    }
}

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 + " говорит: " + message);
    }
}

Скомпилируйте и выполните приведённый выше код, результат вывода:

Name: John
Updated Name: Doe
Doe says: World

java.lang.reflect

java.lang.reflectЭто основной пакет механизма рефлексии Java, предоставляющий классы и интерфейсы для манипулирования классами и их членами (полями, методами, конструкторами и т. д.). С помощью этих API разработчики могут динамически запрашивать и изменять структуру классов во время выполнения.

Ниже приведеныjava.lang.reflectподробные описания основных классов и интерфейсов пакета:

1. ClassКласс

  • Function: Представляет объект класса, предоставляет методы для получения информации о классе, такой как поля, методы, конструкторы и т. д.
  • Основные методы:
    • getFields(): Получить все public-поля.
    • getDeclaredFields(): Получить все объявленные поля, включая private-поля.
    • getMethods(): Получить все public-методы.
    • getDeclaredMethods(): Получить все объявленные методы, включая private-методы.
    • getConstructors(): Получить все public-конструкторы.
    • getDeclaredConstructors(): Получить все объявленные конструкторы, включая private-конструкторы.
    • getSuperclass(): Получить родительский класс класса.
    • getInterfaces(): Получить все интерфейсы, реализуемые классом.

2. FieldКласс

  • Function: Представляет поля класса (атрибуты), предоставляет методы для доступа и изменения значений полей.
  • Основные методы:
    • get(Object obj): Получить значение поля указанного объекта.
    • set(Object obj, Object value): Установить значение поля указанного объекта.
    • getType(): Получить тип данных поля.
    • getModifiers(): Получить модификаторы поля (такие как public, private).

3. MethodКласс

  • Function: Представляет методы класса, предоставляет возможность вызывать методы.
  • Основные методы:
    • invoke(Object obj, Object... args): Вызвать метод указанного объекта.
    • getReturnType(): Получить тип возвращаемого значения метода.
    • getParameterTypes(): Получить типы параметров метода.
    • getModifiers(): Получить модификаторы метода (такие как public, private).

4. ConstructorКласс

  • Function: Представляет конструкторы класса, предоставляет возможность создания объектов.
  • Основные методы:
    • newInstance(Object... initargs): Создать новый экземпляр, используя указанные параметры конструктора.
    • getParameterTypes(): Получить типы параметров конструктора.
    • getModifiers(): Получить модификаторы конструктора (например, public, private).

Пример кода

Ниже приведён пример использованияjava.lang.reflectпакета для операций отражения:

Пример

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 {
        // Получить объект Class
        Class<?> clazz = Car.class;

        // Создать объект Car
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Object car = constructor.newInstance("Toyota", 2020);

        // Доступ к полям и их изменение
        Field modelField = clazz.getDeclaredField("model");
        Field yearField = clazz.getDeclaredField("year");
       
        // Сделать поле доступным (если поле private)
        modelField.setAccessible(true);
        yearField.setAccessible(true);
       
        // Вывести исходное значение поля
        System.out.println("Исходная модель: " + modelField.get(car));
        System.out.println("Исходный год: " + yearField.get(car));
       
        // Изменить значение поля
        modelField.set(car, "Honda");
        yearField.set(car, 2024);
       
        // Вывести изменённое значение поля
        System.out.println("Обновлённая модель: " + modelField.get(car));
        System.out.println("Обновлённый год: " + yearField.get(car));
       
        // Вызвать методы
        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("Автомобиль " + model + " " + year + " года выпуска запускается.");
    }
}

Скомпилируйте и выполните приведённый выше код, результат вывода:

Original Model: Toyota
Original Year: 2020
Updated Model: Honda
Updated Year: 2024
The Honda car of year 2024 is starting.
Другие расширения