Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Ich möchte mich näher mit Reflections auseinandersetzen und hier eine Diskussion anstoßen.
- Habt ihr Reflections mal eingesetzt? Produktiv?
- Wie ist eure Meinung dazu?
- Hat sich in letzter Zeit an dem Thema was geändert?
- Welche Links könnt ihr empfehlen?
Alles, was euch zu dem Thema durch den Kopf geht, her damit. Ich bin neugierig.
Aktiv eingesetzt, eher nein. Indirekt schon sehr häufig (Mockito, Mapstruct, etc.)
Ich war mal in einem Projekt, wo ein Mapping Framework für Druckdaten basierend auf Reflections geschrieben wurde. Das war nicht sinnvoll, weil es schwer wartbar war, man zur Compilezeit keine Fehler sah und der Aufwand das Mapping von Hand zu machen nicht wirklich größer gewesen wäre.
Grundsätzlich ist meine Meinung zu Reflections, und die hat sich auch nicht geändert:
* Toll für ausgereifte, technische Frameworks, die einem Arbeit abnehmen wie eben Mockito oder Mapstruct.
* Im produktiven, fachnahen Code hat das aber nichts zu suchen, weil es ist der Tod von Compile-Zeit Checks, Refactoring & Co. Und lesbar (und damit wartbar) ist es auch selten.
Reflection ist einfach ein Werkzeug, wie viele andere auch. Es ist weder gut noch schlecht. Es hängt von der Aufgabenstellung ab, ob es tauglich ist oder man darauf verzichten soll.
Nur wenn es eine gleichwertige Alternative zu einem Lösungsansatz mit Reflection gibt, ist meist der Ansatz ohne Reflection vorzuziehen.
Ja, ich habe Reflection auch schon in Produktiv-Systemen eingesetzt. Erfahrungsgemäß sind da dann die Fehler-/Exception-Behandlungen ausführlicher.
Ich denke, dass hier fast jeder schon einmal selbst mit Reflection etwas gemacht hat und Deine beiden Fragen würde ich mit "weder noch" beantworten.
Reflection ist weder kompliziert noch uninteressant, jedoch braucht es gute Gründe, sie einzusetzen und das sind eben in erster Linie die von @LimDul genannten Frameworks. Dazu zählen auch Dinge wie JavaBeans, Properties Binding, Validation Framework, Annotation Processing usw. Es gibt also durchaus einige Anwendungsfälle für Reflection.
Hinzu kommt, was genau man unter Reflection versteht: zählt die Klassen-Selbstauskunft via getClass() schon dazu oder der instanceof-Operator? Dann verwendet praktsich jede Implementierung der equals()-Methode schon Reflection...
Ich führe meine Antwort noch mal was aus, warum Reflection gefährlich sein kann.
Typsicherheit
Normaler Code:
Java:
String s = obj.getName();
Hier überprüft der Compiler, dass die Typen passen. Ändere ich den Rückgabewert von Name auf meinen neuen DatenTyp NameMitZusatzInfos meckert der Compiler bzw. die IDE exakt die Stellen an, die ich anpassen muss. Nutze ich Reflections bekomme ich erst zur Laufzeit eine Exception.
Refaktoring
Refactor ich Code mit den mitteln der IDE, bleiben Stellen, die den angepassten Code per Reflection nutzen unangepasst. Ich merke es erst wieder zur Laufzeit mit einer Exception.
Verlust von Invarianten
Habe ich beispielsweise in meiner Klasse folgenden Code
Java:
private String name = "";
public void setName(String name) {
this.name = name == null ? "" : name;
}
Dann kann ich in allen weiteren Methoden in der Klasse sicher sein, dass name niemals null ist. Setze ich das mittels Reflections auf null, gilt die Annahme nicht mehr. Mir fliegt also irgendwo eine NPE. Und wenn ich dann versuche zu analysieren wo die herkommt, ist das extrem aufwendig, weil alle IDE Bordmittel wie Call Hierachie und Co nicht greifen. Und nicht immer kann man mit einem Debugger ran.
Natürlich treffen nicht alle diese Nachteile immer zu und bei geschickter Programmierung kann man die minimieren. Aber ganz weg bekommt man sie nie.
Daher ist eine Variante ohne Reflections in den meisten Fällen immer der bessere weg.
Ich formuliere die Frage mal um: Warum willst du Reflections nutzen?
Ich spiele gerade damit herum, ein Tool zu schreiben, was einen serialisierten Java-Objekt-Graph in einer GUI anzeigt. Und zwar von beliebigen externen Jar-Files, deren Inhalt ich erstmal nicht kenne. Daher bin ich gerade bei Reflections gelandet.
Zum anderen arbeite ich mich näher in das Thema ein, um eventuell nen kleine Vortrag dazu abzuhalten. Und da bin ich dann auch neugierig auf die Meinung in der Community, die bisherigen Erfahrungen etc. Ich bin also für jede Antwort hier dankbar
Was ich selbst noch nicht genau weiß, ist z.B. wie es aktuell mit Änderungen / Neuerungen in dem Bereich aussieht, da es Reflections an sich schon ewig gibt. Und ich hab mal glaub was gelesen von jars, die mit security irgendwie geschützt sind und damit der Code vor Reflections geschützt ist. Aber ich bin da noch nicht so weit mit meiner Recherche. Ich möchte das Thema halt einmal komplett durchgekaut und dann abgehakt haben für mich Und wer will, kann sich hier gern beteiligen.
Reflection ist einfach ein Werkzeug, wie viele andere auch. Es ist weder gut noch schlecht. Es hängt von der Aufgabenstellung ab, ob es tauglich ist oder man darauf verzichten soll.
Exakt, so sehe ich das auch. Manche Werkzeuge sind für die einen Probleme besser geeignet, für andere weniger.
Reflexion hab ich einmal zum Debuggen eingesetzt, und gerade setze ich es wieder ein um Informationen über ein Objekt zu sammeln um es zu speichern (Vermeidung von Problemen mit Zirkelreferenzen).
Und ich hab mal glaub was gelesen von jars, die mit security irgendwie geschützt sind und damit der Code vor Reflections geschützt ist. Aber ich bin da noch nicht so weit mit meiner Recherche.
Jein. Wenn Du mit Modulen arbeitest, werden die Pakete gekapselt, so dass Du zunächst keinen Zugriff darauf hast. Du kannst Pakete exportieren (Abhängigkeiten zur Kompilierzeit ermöglichen) oder aber auch für Reflection öffnen.
@Flown Danke für die Korrektur!
Die Basis gibts seit Java 1.1, aber die meisten Klassen / Methoden stammen aus Java 8, z.B. zur Runtime auf Parameter zuzugreifen: https://openjdk.java.net/jeps/118
Naja, auch nicht ganz korrekt. "Die meisten" Neuerungen gab es mit Java 1.1 (nur "Introspection" möglich), danach folgte noch einiges mit Java 1.2 (Änderungen per Reflection zur Laufzeit vornehmen, z.B. Felder setzen), noch ein bisschen in 1.4, 5 und 6 und ganz ganz gaaaaanz wenig kam mit Java 8 (nämlich nur Parameternamen reflexiv abfragen). Man kann die ab Java 7 hinzugekommenen MethodHandles (bzw. das ganze java.lang.invoke Package) jetzt auch noch zu Reflection hinzurechnen (obwohl es technisch gesehen nicht zur Java Core Reflection API gehört), da es sehr ähnliche Funktionalität bietet wie java.lang.reflect, nur sehr viel performanter ist, da Accessibility-Checks nicht mehr bei jedem Aufruf gemacht werden.
Naja, auch nicht ganz korrekt. "Die meisten" Neuerungen gab es mit Java 1.1 (nur "Introspection" möglich), danach folgte noch einiges mit Java 1.2 (Änderungen per Reflection zur Laufzeit vornehmen, z.B. Felder setzen), noch ein bisschen in 1.4, 5 und 6 und ganz ganz gaaaaanz wenig kam mit Java 8 (nämlich nur Parameternamen reflexiv abfragen). Man kann die ab Java 7 hinzugekommenen MethodHandles (bzw. das ganze java.lang.invoke Package) jetzt auch noch zu Reflection hinzurechnen (obwohl es technisch gesehen nicht zur Java Core Reflection API gehört), da es sehr ähnliche Funktionalität bietet wie java.lang.reflect, nur sehr viel performanter ist, da Accessibility-Checks nicht mehr bei jedem Aufruf gemacht werden.
Es gibt den Aufruf instanceof und das Casten (Person)obj... Ruft dieser Cast intern die Class.cast() Methode auf? Ich gehe davon aus, das beides ist Bestandteil von Reflections?
Sowohl instanceof (und die gleichnamige Bytecode-Instruktion) als auch das Casten (entweder per Java-Syntax oder per Class.cast() Methodenaufruf - letztlich ja die checkcast Bytecode Instruktion) würde ich nicht als Bestandteil von der Reflection API zählen.
Wobei ich mich schon frage, ob man "instanceof" (und getClass()) nicht als Reflection bezeichnen müsste, schließlich wird zur Laufzeit Auskunft über die Datentypen erteilt. In C++ (zumindest in frühen Versionen) gab es derlei Möglichkeiten nicht.
Naja was bytecode instruktionen angeht, bin ich bisher ja total blank! (https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings) wow... ich weiß aber daß das Class.cast(obj) wohl dasselbe macht wie der Cast mittels (Person)obj. Was aber nicht zwingend AUSSAGT, daß das Reflection Inhalt ist... Die Klasse java.lang.Class ist aber ja nicht im reflection package, gehört aber trotzdem zu Reflections dazu, wenn man getClass() nutzt etc.
Wobei ich mich schon frage, ob man "instanceof" (und getClass()) nicht als Reflection bezeichnen müsste, schließlich wird zur Laufzeit Auskunft über die Datentypen erteilt.