EMZETT.
Login

Reflection (Reflexion)

Kurz: Reflection erlaubt einem Programm, zur Laufzeit seine eigene Struktur zu untersuchen und zu verändern: Klassen, Methoden, Felder und Annotationen abfragen, Objekte erzeugen und Methoden aufrufen, deren Namen erst zur Laufzeit feststehen.

Genauer: Frameworks nutzen Reflection intensiv: Dependency-Injection-Container (Dependency Injection), ORMs, Serialisierer (Serialisierung) und Test-Frameworks finden Klassen und Methoden anhand ihrer Namen oder Annotationen, ohne sie zur Übersetzungszeit zu kennen.

Im Detail

Class<?> k = Class.forName("java.util.ArrayList");
Object liste = k.getDeclaredConstructor().newInstance();
k.getMethod("add", Object.class).invoke(liste, "Hallo");
System.out.println(liste);                 // [Hallo]
for (var m : k.getMethods()) System.out.println(m.getName());
class Person:
    def __init__(self):
        self.name = "Mia"
    def gruss(self):
        return "Hallo " + self.name
 
p = Person()
print(dir(p))                              # alle Attribute und Methoden
print(getattr(p, "name"))                  # Mia
setattr(p, "name", "Tom")
print(getattr(p, "gruss")())               # Hallo Tom
print(hasattr(p, "alter"), type(p).__name__)
const o = { a: 1, b: 2 };
console.log(Object.keys(o), Reflect.has(o, "a"));

Vor- und Nachteile

VorteileNachteile
sehr flexible Frameworkslangsamer als direkte Aufrufe
Konfiguration statt CodeFehler erst zur Laufzeit statt beim Übersetzen
generische Werkzeuge (Serialisierer, Test-Runner)kann Kapselung umgehen und Sicherheitsrisiken bergen

Sprachen mit starker Metaprogrammierung (Makros) lösen vieles schon zur Übersetzungszeit; Rust und Go setzen bewusst weniger auf Reflection.

Siehe auch: Annotationen, Dependency Injection, Serialisierung, Makros