Das Reflection-API dient dazu, die Bestandteile von Klassen (Datenelemente, Konstruktoren und Methoden) dynamisch zur Laufzeit zu analysieren und zu benutzen. Es gestattet somit, in einem Java-Programm Klassen und Interfaces zu benutzen, die zum Zeitpunkt des Kompilierens noch nicht bekannt sind. Das Reflection-API wird unter anderem in folgenden Fällen eingesetzt:
- Das dynamische Laden von Klassen in eine Anwendung und die Erzeugung von zugehörigen Exemplaren. Ein häufiger Anwendungsfall hierfür ist das dynamische Einbinden von Klassen, die eine Art Treiberfunktion haben. Der Name der Treiberklasse wird dabei oft in einer Konfigurationsdatei angegeben und beim Start der Applikation ausgelesen. Anschließend kann mit einem Konstruktoraufruf über das Reflection-API ein Exemplar der Treiberklasse erzeugt werden.
Solange man nur parameterlose Konstruktoren aufrufen will, kann man hier wie im Beispiel für die Methode Class.newInstance() im Abschnit xxx verfahren. Sobald aber Parameter übergeben werden sollen, muss auf das Reflection-API zurückgegriffen werden.
- Auch bei Java-Beans kommt das Reflection-API zum Einsatz, um die Datenelemente der Bean-Klassen (in diesem Kontext meist Properties genannt) zu ermitteln und deren Werte auszulesen bzw. neu zu setzen. Diese Properties sind zwar spezifisch für alle Bean-Klassen, jedoch folgen die Bean-Properties einem Muster: Zum Einstellen einer Property gibt es eine setXXX()-Methode und zum Auslesen eine eine getXXX-Methode, wobei XXX für den Namen der Property steht. Anhand dieses Musters kann eine Anwendung die Properties einer Bean-Klasse erkennen, indem sie nach diesen setXXX()- und getXXX-Methoden sucht.
Allgemeiner kann man sagen, dass der Einsatz des Reflection-API immer dann erforderlich ist, wenn zur Laufzeit Klassen eingebunden werden sollen,
- die zum Compile-Zeitpunkt noch nicht bekannt sind
- oder deren Schnittstellen nicht durch Interfaces oder abstrakte Klassen definiert sind, sondern nur Schnittstellenkonventionen und -mustern folgen.
Für den dynamischen Zugriff auf die Klassenbestandteile definiert das Reflection-API die Klassen
ConstructorMethodFieldgetConstructor(),
getMethod() und
getField() der Klasse Class. Es muss also zunächst immer das Class-Objekt für die Klasse ermittelt werden, auf deren Bestandteile dynamisch zugegriffen werden soll. Auch wenn das Reflection-API ein großes Maß an Flexibilität mit sich bringt, sollte man sie nur dort einsetzen, wo es wirklich erforderlich ist. Denn dadurch bedingt, dass das Erzeugen von Exemplaren und die Aufrufe von Methoden völlig dynamisch erfolgen, kann der Compiler keine der sonst üblichen Prüfungen auf korrekte Datentypen durchführen. Das gleiche gilt auch für Checks, ob
geprüfte Exceptions korrekt behandelt werden. Daher sollte man stets bestrebt sein, den Einsatz des Reflection-API auf das notwendige Maß zu beschränken, damit bereits der Compiler die Typsicherheit und die ordnungsgemäße Handhabung von Exceptions gewährleisten kann.