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
| Vorteile | Nachteile |
|---|---|
| sehr flexible Frameworks | langsamer als direkte Aufrufe |
| Konfiguration statt Code | Fehler 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