CodeGym /Kurse /JAVA 25 SELF /Einführung in die Reflexion: die Klasse Class, wozu sie g...

Einführung in die Reflexion: die Klasse Class, wozu sie gebraucht wird

JAVA 25 SELF
Level 62 , Lektion 0
Verfügbar

1. Was ist Reflexion

Reflexion in Java ist ein Mechanismus, der es einem Programm erlaubt, seine eigene Struktur zur Laufzeit zu untersuchen und sogar zu ändern. Es ist, als könnten Sie in sich selbst hineinschauen und feststellen: „Welche Felder und Methoden habe ich? Welchen Konstruktor habe ich? Welche Klasse bin ich überhaupt?“ – und sogar eine private Methode aufrufen.

Formale Definition:
Reflexion ist eine API, die es erlaubt, zur Laufzeit Informationen über Klassen, Interfaces, Felder, Methoden und Konstruktoren zu erhalten und mit ihnen zu arbeiten.

Wozu braucht man Reflexion?

  • Frameworks: Spring, Hibernate, JUnit verwenden Reflexion für „Magie“: automatisches Erzeugen von Objekten, Dependency Injection, Aufruf von Methoden nach Namen und per Annotationen.
  • Serialisierung: Objekte in JSON/XML umwandeln und zurück – man muss Felder erkennen und auf sie zugreifen können.
  • Testen: Methoden mit Annotationen (z. B. @Test) automatisch finden und aufrufen.
  • Dynamisches Laden von Klassen: Laden einer Klasse zur Laufzeit per Namen (Plugins, Treiber).
  • IDEs und Code-Analyse: Autovervollständigung, Inspektionen, Refactoring.

Beispiel aus dem Alltag

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

    public void sayHello() {
        System.out.println("Hallo, ich heiße " + name);
    }
}

Mit Reflexion können wir zur Laufzeit herausfinden, dass die Klasse Person die Felder name und age sowie die Methode sayHello hat. Darüber hinaus kann man den Wert eines privaten Feldes ändern oder eine Methode per Name aufrufen.

Ein wenig Humor
Man kann sagen, dass Reflexion wie in „Matrix“ ist: Sie erkennen, dass Ihr ganzer Code Daten sind, die man im laufenden Betrieb untersuchen und ändern kann. Vergessen Sie nur nicht die rote Sicherheits‑Pille!

2. Die Klasse Class: das Herz der Reflexion

In Java ist zur Laufzeit jedes Objekt und jeder Typ mit einem besonderen Objekt vom Typ Class verbunden. Dieses Objekt ist die „Metainformation“ über den Typ. Die Klasse java.lang.Class<T> ist der zentrale Einstiegspunkt in die Welt der Reflexion.

Wie erhält man ein Objekt Class?

Es gibt mehrere Wege:

  • Über .class
    Der direkteste und sicherste Weg, wenn die Klasse zur Kompilierzeit bekannt ist:
    Class<Person> personClass = Person.class;
  • Über ein Objekt: getClass()
    Wenn Sie bereits eine Instanz haben:
    Person p = new Person();
    Class<?> clazz = p.getClass();
    Hier ist clazz das Objekt Class, das die tatsächliche Klasse des Objekts p beschreibt.
  • Über einen String: Class.forName()
    Wenn der Klassenname nur zur Laufzeit bekannt ist:
    Class<?> clazz = Class.forName("com.example.Person");
    Geeignet zum Laden von Plugins, Treibern und sonstiger Dynamik.

Beispiel: Ermitteln des Klassennamens

Person p = new Person();
Class<?> clazz = p.getClass();
System.out.println(clazz.getName()); // Gibt aus: Person oder com.example.Person

Tabelle: Wichtige Möglichkeiten, ein Objekt Class zu erhalten

Wie erhalten Wann verwenden Beispiel
MyClass.class
Wenn die Klasse zur Kompilierzeit bekannt ist
String.class
object.getClass()
Wenn ein Objekt vorhanden ist
someList.getClass()
Class.forName(name)
Wenn der Klassenname zur Laufzeit bekannt ist
Class.forName("java.util.Date")

Schema: Objekt und sein Class

+-------------------+
|   Person p        |
+-------------------+
         |
         v
+-------------------+
|  p.getClass()     |
+-------------------+
         |
         v
+-------------------+
|   Class<Person>   |
+-------------------+

Typprüfung über Class

Manchmal muss man feststellen, ob ein Objekt zu einer bestimmten Klasse gehört:

if (p.getClass() == Person.class) {
    System.out.println("Das ist definitiv eine Person!");
}

Oder unter Berücksichtigung der Vererbung – der normale Operator instanceof:

if (p instanceof Person) {
    // funktioniert wie üblich
}

3. Wann Reflexion nötig ist – und wann nicht

Mit großer Macht kommt große Verantwortung. Reflexion ist ein mächtiges Werkzeug, aber man sollte sie nur einsetzen, wenn es wirklich notwendig ist.

Wo Reflexion notwendig ist

  • Frameworks und Bibliotheken: Spring, Hibernate, JUnit, Jackson – Automatisierung, „Magie“ und weniger „Handarbeit“ im Code.
  • Serialisierung: Man muss die Felder eines Objekts kennen, um es in JSON/XML zu verwandeln.
  • Plugins und Erweiterungen: Klassen werden dynamisch geladen, ihre Struktur ist vorher unbekannt.

Warum man Reflexion nicht überstrapazieren sollte

  • Verlust der Typsicherheit: Fehler treten erst zur Laufzeit auf.
  • Wartbarkeit: Der Code wird weniger offensichtlich.
  • Leistung: Langsamer als direkte Aufrufe.
  • Sicherheit: Man kann die Kapselung umgehen und private Daten offenlegen.

Beispiel: Wenn Reflexion nicht nötig ist

p.sayHello();

Beispiel: Wenn Reflexion ein Muss ist
Sie schreiben ein Mini‑Testframework: Der Nutzer markiert Methoden mit der Annotation @Test, und das Programm soll sie automatisch finden und aufrufen – ohne Reflexion geht das nicht.

4. Demonstration: Einstieg in Class

Beispiel: Ausgabe des Klassennamens und seiner Superklasse

public class ReflectionDemo {
    public static void main(String[] args) {
        String s = "Hello, reflection!";
        Class<?> clazz = s.getClass();

        System.out.println("Klassenname: " + clazz.getName());
        System.out.println("Einfacher Klassenname: " + clazz.getSimpleName());
        System.out.println("Paket: " + clazz.getPackageName());
        System.out.println("Oberklasse: " + clazz.getSuperclass().getName());
    }
}

Ergebnis:

Klassenname: java.lang.String
Einfacher Klassenname: String
Paket: java.lang
Oberklasse: java.lang.Object

Beispiel: Class für primitive Typen erhalten

Class<Integer> intClass = int.class;
System.out.println(intClass.getName()); // int

Class<?> doubleClass = double.class;
System.out.println(doubleClass.getName()); // double

Beispiel: Class für ein Array erhalten

int[] arr = new int[10];
Class<?> arrClass = arr.getClass();
System.out.println(arrClass.getName()); // [I (spezifisches Format für Arrays)

Beispiel: Prüfung der Zugehörigkeit zu einem Typ

if (arrClass.isArray()) {
    System.out.println("Das ist ein Array!");
}

5. Praxis: Mini‑Programm „Was für eine Klasse?“

Schreiben wir ein Programm, das den vollqualifizierten Klassennamen entgegennimmt (zum Beispiel "java.util.ArrayList") und grundlegende Informationen darüber ausgibt.

import java.util.Scanner;

public class ClassInfoPrinter {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Geben Sie den vollständigen Klassennamen ein: ");
        String className = scanner.nextLine();

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

        System.out.println("Klassenname: " + clazz.getName());
        System.out.println("Paket: " + clazz.getPackageName());
        System.out.println("Oberklasse: " + clazz.getSuperclass().getName());

        Class<?>[] interfaces = clazz.getInterfaces();
        System.out.print("Implementiert Schnittstellen: ");
        for (Class<?> i : interfaces) {
            System.out.print(i.getName() + " ");
        }
        System.out.println();
    }
}

Beispielausgabe:

Geben Sie den vollständigen Klassennamen ein: java.util.ArrayList
Klassenname: java.util.ArrayList
Paket: java.util
Oberklasse: java.util.AbstractList
Implementiert Schnittstellen: java.util.List java.util.RandomAccess java.lang.Cloneable java.io.Serializable 

Interessante Fakten zu Class und Reflexion

  • Jeder geladene Typ in der JVM hat einen gemeinsamen Repräsentanten – ein Objekt Class. Alle Instanzen eines Typs teilen sich dasselbe Class<T>.
  • Man kann die Art des Typs bestimmen: isInterface(), isEnum(), isArray(), isPrimitive() usw.
  • Gibt man in Class.forName einen falschen Namen an, erhält man die Ausnahme ClassNotFoundException.
  • Mit Reflexion kann man Objekte erzeugen, ohne die Klasse zur Kompilierzeit zu kennen – darüber sprechen wir in der nächsten Vorlesung.

6. Typische Fehler beim ersten Kontakt mit Reflexion

Fehler Nr. 1: Zu erwarten, dass Reflexion schnell ist.
Tatsächlich ist Reflexion langsamer als normale Methodenaufrufe und Feldzugriffe. Verwenden Sie sie nicht für jede Kleinigkeit.

Fehler Nr. 2: Versuch, ein Class für eine nicht vorhandene Klasse zu bekommen.
Wenn Sie sich im Namen vertun, erhalten Sie ClassNotFoundException. Behandeln Sie diese Ausnahme.

Fehler Nr. 3: Verwechslung zwischen Class‑Objekt und Instanz.
Das Objekt Class beschreibt die Struktur eines Typs und ist nicht dessen Instanz.

Fehler Nr. 4: Reflexion ohne Notwendigkeit einsetzen.
Wenn es mit normalem Code geht – machen Sie es besser so. Reflexion ist für Dynamik, Frameworks, Plugins und ähnliche Aufgaben gedacht.

Fehler Nr. 5: Unvorsichtiger Umgang mit privaten Feldern und Methoden.
Reflexion erlaubt es, die Kapselung zu umgehen, was zu Fehlern und Sicherheitsproblemen führen kann – insbesondere in großen Projekten.

1
Aufgabe
JAVA 25 SELF, Level 62, Lektion 0
Gesperrt
Identifikation des digitalen "Bauplans" 📚
Identifikation des digitalen "Bauplans" 📚
1
Aufgabe
JAVA 25 SELF, Level 62, Lektion 0
Gesperrt
Magische Schriftrollen nach Namen suchen 🧙
Magische Schriftrollen nach Namen suchen 🧙
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION