Java-Reflexion

Java-Reflexion ist eine leistungsstarke Funktion, die es Programmen ermöglicht, Informationen über Klassen, Schnittstellen, Felder und Methoden zur Laufzeit abzufragen, darauf zuzugreifen und sie zu ändern. Die Reflexion bietet die Möglichkeit, Klassen dynamisch zu manipulieren, was in vielen Frameworks und Bibliotheken weit verbreitet ist, z. B. bei der Dependency Injection im Spring-Framework.

Reflexions-API

Die Reflexions-API von Java bietet eine Reihe von Klassen und Schnittstellen zur Manipulation von Class-Objekten. Zu den wichtigsten Klassen gehören:

  • java.lang.Class: Repräsentiert ein Class-Objekt. Bietet Methoden zum Abrufen der Felder, Methoden, Konstruktoren usw. der Klasse.
  • java.lang.reflect.Field: Repräsentiert die Felder (Attribute) einer Klasse. Bietet die Möglichkeit, auf Felder zuzugreifen und sie zu ändern.
  • java.lang.reflect.Method: Repräsentiert die Methoden einer Klasse. Bietet die Möglichkeit, Methoden aufzurufen.
  • java.lang.reflect.Constructor: Repräsentiert die Konstruktoren einer Klasse. Bietet die Möglichkeit, Objekte zu erstellen.

Workflow

  1. AbrufenClassObject: Zuerst das Class-Objekt der Zielklasse abrufenClassObjekt.
  2. Member-Informationen abrufen: Über dasClassObjekt, können Sie Informationen über die Felder, Methoden, Konstruktoren usw. der Klasse abrufen.
  3. Member manipulieren: Über die Reflection-API können Sie Feldwerte lesen und ändern, Methoden aufrufen und Objekte erstellen.

Im Folgenden finden Sie die grundlegenden Verwendungsmethoden der Java-Reflection und ihre gängigen Anwendungen.

1. Abrufen des Class-Objekts

Jede Klasse hat ein zugehöriges Class-Objekt in der JVM. Sie können das Class-Objekt auf folgende Weise abrufen:

Über Klassenliterale

Class<?> clazz = String.class;

Über eine Objektinstanz:

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

Über die Methode Class.forName():

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

2. Objekte erstellen

Sie können Reflection verwenden, um Objekte dynamisch zu erstellen:

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

3. Zugriff auf Felder

Sie können über Reflection auf Klassenfelder zugreifen und sie ändern:

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

4. Aufrufen von Methoden

Sie können Klassenmethoden über Reflection aufrufen:

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

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

5. Konstruktoren abrufen

Sie können Reflection verwenden, um Konstruktoren abzurufen und aufzurufen:

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

6. Schnittstellen und Elternklassen abrufen

Sie können Reflection verwenden, um die von der Klasse implementierten Schnittstellen und ihre Elternklasse abzurufen:

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

Das folgende ist ein vollständiges Beispiel, das zeigt, wie man Reflection verwendet, um Objekte zu erstellen, auf Felder zuzugreifen und Methoden aufzurufen:

Beispiel

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 {
        // Das Class-Objekt abrufen
        Class<?> clazz = Person.class;
       
        // Ein Objekt erstellen
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Object person = constructor.newInstance("John", 30);
       
        // Auf Felder zugreifen
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true);
        System.out.println("Name: " + nameField.get(person));
       
        // Felder ändern
        nameField.set(person, "Doe");
        System.out.println("Aktualisierter Name: " + nameField.get(person));
       
        // Methoden aufrufen
        Method greetMethod = clazz.getMethod("greet", String.class);
        greetMethod.invoke(person, "Welt");
    }
}

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 + " sagt: " + message);
    }
}

Kompilieren und führen Sie den obigen Code aus, das Ausgabeergebnis ist:

Name: John
Updated Name: Doe
Doe says: World

java.lang.reflect

java.lang.reflectEs ist das Kernpaket des Java-Reflection-Mechanismus und stellt Klassen und Schnittstellen für die Manipulation von Klassen und deren Mitgliedern (Felder, Methoden, Konstruktoren usw.) bereit. Über diese APIs können Entwickler die Struktur von Klassen zur Laufzeit dynamisch abfragen und ändern.

Die folgenden sindjava.lang.reflectausführliche Einführungen zu den Hauptklassen und Schnittstellen im Paket:

1. ClassKlasse

  • Funktion: Repräsentiert ein Klassenobjekt und bietet Methoden zum Abrufen von Klasseninformationen, wie Felder, Methoden, Konstruktoren usw.
  • Hauptmethoden:
    • getFields(): Alle öffentlichen Felder abrufen.
    • getDeclaredFields(): Alle deklarierten Felder abrufen, einschließlich privater Felder.
    • getMethods(): Alle öffentlichen Methoden abrufen.
    • getDeclaredMethods(): Alle deklarierten Methoden abrufen, einschließlich privater Methoden.
    • getConstructors(): Alle öffentlichen Konstruktoren abrufen.
    • getDeclaredConstructors(): Alle deklarierten Konstruktoren abrufen, einschließlich privater Konstruktoren.
    • getSuperclass(): Die Elternklasse der Klasse abrufen.
    • getInterfaces(): Ruft alle von der Klasse implementierten Schnittstellen ab.

2. FieldKlasse

  • Function: Stellt die Felder (Attribute) einer Klasse dar, bietet Methoden, um auf Feldwerte zuzugreifen und sie zu ändern.
  • Hauptmethoden:
    • get(Object obj): Ruft den Feldwert des angegebenen Objekts ab.
    • set(Object obj, Object value): Legt den Feldwert des angegebenen Objekts fest.
    • getType(): Ruft den Datentyp des Felds ab.
    • getModifiers(): Ruft die Modifikatoren des Felds ab (wie public, private).

3. MethodKlasse

  • Function: Stellt die Methoden einer Klasse dar, bietet die Möglichkeit, Methoden aufzurufen.
  • Hauptmethoden:
    • invoke(Object obj, Object... args): Ruft die Methode des angegebenen Objekts auf.
    • getReturnType(): Ruft den Rückgabetyp der Methode ab.
    • getParameterTypes(): Ruft die Parametertypen der Methode ab.
    • getModifiers(): Ruft die Modifikatoren der Methode ab (wie public, private).

4. ConstructorKlasse

  • Function: Stellt die Konstruktoren einer Klasse dar, bietet die Möglichkeit, Objekte zu erstellen.
  • Hauptmethoden:
    • newInstance(Object... initargs): Erzeuge eine neue Instanz mit den angegebenen Konstruktorparametern.
    • getParameterTypes(): Ermittle die Parametertypen des Konstruktors.
    • getModifiers(): Ermittle die Modifikatoren des Konstruktors (wie public, private).

Beispielcode

Das Folgende ist ein Beispiel unter Verwendung desjava.lang.reflectPakets für Reflection-Operationen:

Beispiel

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 {
        // Das Class-Objekt abrufen
        Class<?> clazz = Car.class;

        // Ein Car-Objekt erstellen
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Object car = constructor.newInstance("Toyota", 2020);

        // Auf Felder zugreifen und sie ändern
        Field modelField = clazz.getDeclaredField("model");
        Field yearField = clazz.getDeclaredField("year");
       
        // Das Feld als zugänglich festlegen (falls das Feld private ist)
        modelField.setAccessible(true);
        yearField.setAccessible(true);
       
        // Ursprünglichen Feldwert ausgeben
        System.out.println("Ursprüngliches Modell: " + modelField.get(car));
        System.out.println("Ursprüngliches Jahr: " + yearField.get(car));
       
        // Feldwert ändern
        modelField.set(car, "Honda");
        yearField.set(car, 2024);
       
        // Geänderten Feldwert ausgeben
        System.out.println("Aktualisiertes Modell: " + modelField.get(car));
        System.out.println("Aktualisiertes Jahr: " + yearField.get(car));
       
        // Methoden aufrufen
        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("Das " + model + " Auto aus dem Jahr " + year + " startet.");
    }
}

Kompilieren und führen Sie den obigen Code aus, das Ausgabeergebnis ist:

Original Model: Toyota
Original Year: 2020
Updated Model: Honda
Updated Year: 2024
The Honda car of year 2024 is starting.
Andere Erweiterungen