CodeGym /Kurse /JAVA 25 SELF /Informationen über Klassen, Felder, Methoden abrufen

Informationen über Klassen, Felder, Methoden abrufen

JAVA 25 SELF
Level 62, Lektion 1
Verfügbar

1. Informationen über Felder abrufen

Worin unterscheiden sich getFields() und getDeclaredFields()

In Java hat jede Klasse Felder (fields) – Variablen, die innerhalb der Klasse deklariert sind. Mithilfe von Reflection können wir ihre Namen, Typen, Zugriffsmodifizierer (public/private) ermitteln und zur Laufzeit auf sie zugreifen. Der Haupteinstiegspunkt ist das Objekt Class<?>.

Wichtige Methoden der Klasse Class für die Arbeit mit Feldern:

Methode Was wird zurückgegeben
getFields()
Ein Array aller public-Felder der Klasse, ihrer Oberklassen und Interfaces
getDeclaredFields()
Ein Array aller in dieser Klasse deklarierten Felder

Analogie: getFields() – wie eine Führung nur durch die Schauräume (public), und getDeclaredFields() – auch durch die Technikräume (private, protected, package-private).

Beispiel: Alle Felder der Klasse ausgeben

Angenommen, wir haben eine Klasse:

public class Person {
    public String name;
    private int age;
    protected String email;
}

Wir holen die Informationen über die Felder:

import java.lang.reflect.Field;

Class<?> clazz = Person.class;

// Alle public-Felder (einschließlich geerbter)
System.out.println("Public fields:");
for (Field field : clazz.getFields()) {
    System.out.println(field.getName() + " : " + field.getType().getSimpleName());
}

// Alle deklarierten Felder (einschließlich private, nur eigene)
System.out.println("\nDeclared fields:");
for (Field field : clazz.getDeclaredFields()) {
    System.out.println(field.getName() + " : " + field.getType().getSimpleName());
}

Ergebnis:

Public fields:
name : String

Declared fields:
name : String
age : int
email : String

Wie ermittelt man die Modifizierer eines Feldes?

Jedes Feld (Field) hat Modifizierer (public/private/protected, static, final usw.). Man kann sie über getModifiers() abrufen und mit Modifier in eine Zeichenkette umwandeln:

import java.lang.reflect.Modifier;

for (Field field : clazz.getDeclaredFields()) {
    int mods = field.getModifiers();
    System.out.println(field.getName() + " : " + Modifier.toString(mods));
}

2. Informationen über Methoden abrufen

Methoden getMethods() und getDeclaredMethods()

Methoden sind die Aktionen, die ein Objekt ausführen kann. Mit Reflection kann man herausfinden, welche Methoden eine Klasse hat, ihre Parameter, Rückgabetypen, Modifizierer und Annotationen.

Methode Was wird zurückgegeben
getMethods()
Alle public-Methoden der Klasse und ihrer Oberklassen (einschließlich Object)
getDeclaredMethods()
Alle in dieser Klasse deklarierten Methoden (einschließlich private)

Beispiel: Alle Methoden der Klasse ausgeben

import java.lang.reflect.Method;

System.out.println("Public methods:");
for (Method method : clazz.getMethods()) {
    System.out.println(method.getName());
}

System.out.println("\nDeclared methods:");
for (Method method : clazz.getDeclaredMethods()) {
    System.out.println(method.getName());
}

Ergebnis (für Person):

Public methods:
getClass
hashCode
equals
toString
notify
notifyAll
wait
wait
wait

Declared methods:
(nichts, wenn in Person keine eigenen Methoden deklariert sind)

Fügen wir eine Methode zu Person hinzu:

public class Person {
    public String name;
    private int age;
    protected String email;

    public void sayHello() {
        System.out.println("Hi!");
    }
}

Jetzt zeigt getDeclaredMethods() auch diese an.

Wie ermittelt man Parameter und Rückgabetyp einer Methode?

for (Method method : clazz.getDeclaredMethods()) {
    System.out.print(Modifier.toString(method.getModifiers()) + " ");
    System.out.print(method.getReturnType().getSimpleName() + " ");
    System.out.print(method.getName() + "(");
    Class<?>[] params = method.getParameterTypes();
    for (int i = 0; i < params.length; i++) {
        System.out.print(params[i].getSimpleName());
        if (i < params.length - 1) System.out.print(", ");
    }
    System.out.println(");");
}

Ausgabe:

public void sayHello();

3. Informationen über Konstruktoren abrufen

Konstruktoren sind spezielle Methoden, mit denen Objekte erstellt werden.

Methode Was wird zurückgegeben
getConstructors()
Alle public-Konstruktoren
getDeclaredConstructors()
Alle in der Klasse deklarierten Konstruktoren

Beispiel: Alle Konstruktoren der Klasse ausgeben

import java.lang.reflect.Constructor;

System.out.println("Constructors:");
for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
    System.out.print(clazz.getSimpleName() + "(");
    Class<?>[] params = constructor.getParameterTypes();
    for (int i = 0; i < params.length; i++) {
        System.out.print(params[i].getSimpleName());
        if (i < params.length - 1) System.out.print(", ");
    }
    System.out.println(");");
}

Wenn in der Klasse nur der Standardkonstruktor deklariert ist, wird auch dieser ausgegeben.

4. Annotationen: Wie findet man heraus, womit Klasse, Methode oder Feld annotiert sind

Annotationen sind spezielle Markierungen, die man an Klassen, Methoden, Feldern und Parametern anbringen kann. Mit Reflection kann man ermitteln, welche Annotationen ein Element hat.

Annotationen abrufen

  • Für die Klasse: clazz.getAnnotations()
  • Für die Methode: method.getAnnotations()
  • Für das Feld: field.getAnnotations()

Beispiel: Prüfen, ob die Annotation @Deprecated vorhanden ist

for (Method method : clazz.getDeclaredMethods()) {
    if (method.isAnnotationPresent(Deprecated.class)) {
        System.out.println(method.getName() + " is @Deprecated");
    }
}

Beispiel: Alle Annotationen der Klasse ausgeben

for (var annotation : clazz.getAnnotations()) {
    System.out.println(annotation);
}

5. Praxis: Mini-Programm zur Analyse der Klassenstruktur

Fassen wir alles zusammen und schreiben ein kleines Hilfsprogramm, das anhand des Klassennamens seine Struktur ausgibt: Felder, Methoden, Konstruktoren und Annotationen.

Codebeispiel: ClassInspector

import java.lang.reflect.*;
import java.util.Scanner;

public class ClassInspector {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Geben Sie den vollqualifizierten Klassennamen ein (z. B. java.util.ArrayList): ");
        String className = scanner.nextLine();

        Class<?> clazz = Class.forName(className);

        System.out.println("\n== Klasse: " + clazz.getName() + " ==");

        // Annotationen der Klasse
        System.out.println("Annotationen:");
        for (Annotation annotation : clazz.getAnnotations()) {
            System.out.println("  " + annotation);
        }

        // Felder
        System.out.println("\nFelder:");
        for (Field field : clazz.getDeclaredFields()) {
            System.out.println("  " + Modifier.toString(field.getModifiers())
                    + " " + field.getType().getSimpleName()
                    + " " + field.getName());
        }

        // Methoden
        System.out.println("\nMethoden:");
        for (Method method : clazz.getDeclaredMethods()) {
            System.out.print("  " + Modifier.toString(method.getModifiers())
                    + " " + method.getReturnType().getSimpleName()
                    + " " + method.getName() + "(");
            Class<?>[] params = method.getParameterTypes();
            for (int i = 0; i < params.length; i++) {
                System.out.print(params[i].getSimpleName());
                if (i < params.length - 1) System.out.print(", ");
            }
            System.out.println(");");
        }

        // Konstruktoren
        System.out.println("\nKonstruktoren:");
        for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
            System.out.print("  " + Modifier.toString(constructor.getModifiers())
                    + " " + clazz.getSimpleName() + "(");
            Class<?>[] params = constructor.getParameterTypes();
            for (int i = 0; i < params.length; i++) {
                System.out.print(params[i].getSimpleName());
                if (i < params.length - 1) System.out.print(", ");
            }
            System.out.println(");");
        }
    }
}

Wie funktioniert das?

  • Der Benutzer gibt den vollqualifizierten Klassennamen ein (z. B. "java.util.ArrayList" oder eine eigene Klasse).
  • Das Programm lädt die Klasse dynamisch und gibt ihre Annotationen, Felder, Methoden und Konstruktoren aus.
  • Probieren Sie es mit Standardklassen der JDK – Sie werden sehen, wie viel Interessantes darin steckt!

6. Nützliche Details und Visualisierung

Schaubild: Was man über eine Klasse per Reflection herausfinden kann

graph TD
    A[Class<?>] --> B["getFields/getDeclaredFields"]
    A --> C[getMethods/getDeclaredMethods]
    A --> D[getConstructors/getDeclaredConstructors]
    A --> E[getAnnotations]
    B --> F[Field: Typ, Name, Modifizierer]
    C --> G[Method: Rückgabetyp, Parameter]
    D --> H[Constructor: Parameter]
    E --> I["Annotation[]"]

Tabelle: Wo finde ich welche Information

Was wollen wir wissen Wie per Reflection abrufen
Alle public-Felder
clazz.getFields()
Alle deklarierten Felder
clazz.getDeclaredFields()
Alle public-Methoden
clazz.getMethods()
Alle deklarierten Methoden
clazz.getDeclaredMethods()
Alle public-Konstruktoren
clazz.getConstructors()
Alle deklarierten Konstruktoren
clazz.getDeclaredConstructors()
Annotationen der Klasse
clazz.getAnnotations()
Annotationen von Methode/Feld
method.getAnnotations(), field.getAnnotations()
Modifizierer
Modifier.toString(field.getModifiers())

7. Typische Fehler beim Arbeiten mit Reflection

Fehler Nr. 1: getFields() und getDeclaredFields() werden verwechselt.
Wenn Sie private-Felder suchen, verwenden Sie getDeclaredFields() und nicht getFields(). Ersteres liefert alle in der Klasse deklarierten Felder, Letzteres nur public (und geerbte!).

Fehler Nr. 2: Checked Exceptions werden nicht behandelt.
Viele Reflection-APIs werfen Ausnahmen (z. B. ClassNotFoundException oder SecurityException). Vergessen Sie nicht, sie zu behandeln oder in der Methodensignatur zu deklarieren.

Fehler Nr. 3: Zugriffsmodifizierer werden nicht berücksichtigt.
Zugriff auf private-Felder und -Methoden ist nur nach Aufruf von setAccessible(true) möglich, sonst gibt es eine IllegalAccessException. Beispiel:

Field field = clazz.getDeclaredField("age");
field.setAccessible(true); // Zugriff auf das private Feld erlauben
int value = (int) field.get(person);

Fehler Nr. 4: Es werden nur eigene Methoden/Felder erwartet.
getMethods() und getFields() liefern public-Member nicht nur der aktuellen Klasse, sondern auch aller Oberklassen, einschließlich Object. Das kann überraschen, wenn Sie nur das sehen wollen, was Sie selbst geschrieben haben.

Fehler Nr. 5: Vorhandensein von Annotationen wird falsch geprüft.
Verwenden Sie isAnnotationPresent() zur Prüfung auf eine konkrete Annotation, statt ohne Not den Array der Annotationen manuell zu durchlaufen.

1
Aufgabe
JAVA 25 SELF, Level 62, Lektion 1
Gesperrt
Audit des geheimen Geräts 🕵️
Audit des geheimen Geräts 🕵️
1
Aufgabe
JAVA 25 SELF, Level 62, Lektion 1
Gesperrt
Katalogisierung antiker Rituale 📜
Katalogisierung antiker Rituale 📜
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION