Was ist Reflexion und warum ist sie nützlich?
Ich interessiere mich besonders für Java, aber ich gehe davon aus, dass die Prinzipien in jeder Sprache gleich sind.
java
reflection
terminology
Lehane
quelle
quelle
@Jailbreak
. Es bietet direkten, typsicheren Zugriff auf private Felder, Methoden usw. Lassen Sie den Java-Compiler Ihren Code sicher überprüfen und Manifold den zugrunde liegenden Reflection-Zugriff für Sie generieren. Weitere Informationen: manifold.systems/docs.html#type-safe-reflectionAntworten:
Die Namensreflexion wird verwendet, um Code zu beschreiben, der anderen Code im selben System (oder selbst) überprüfen kann.
Angenommen, Sie haben ein Objekt eines unbekannten Typs in Java und möchten eine 'doSomething'-Methode aufrufen, falls eine vorhanden ist. Das statische Typisierungssystem von Java ist nicht wirklich darauf ausgelegt, dies zu unterstützen, es sei denn, das Objekt entspricht einer bekannten Schnittstelle. Mithilfe von Reflection kann Ihr Code das Objekt jedoch überprüfen und herausfinden, ob es eine Methode namens "doSomething" enthält, und es dann aufrufen, wenn Sie dies tun möchte.
Um Ihnen ein Codebeispiel dafür in Java zu geben (stellen Sie sich vor, das betreffende Objekt ist foo):
Ein sehr häufiger Anwendungsfall in Java ist die Verwendung mit Anmerkungen. JUnit 4 verwendet beispielsweise Reflection, um Ihre Klassen nach Methoden zu durchsuchen, die mit der Annotation @Test gekennzeichnet sind, und ruft sie dann beim Ausführen des Komponententests auf.
Unter http://docs.oracle.com/javase/tutorial/reflect/index.html finden Sie einige gute Beispiele für Überlegungen
Und schließlich, ja, sind die Konzepte in anderen statisch typisierten Sprachen, die die Reflexion unterstützen (wie C #), ziemlich ähnlich. In dynamisch typisierten Sprachen ist der oben beschriebene Anwendungsfall weniger erforderlich (da der Compiler zulässt, dass eine Methode für ein Objekt aufgerufen wird und zur Laufzeit fehlschlägt, wenn sie nicht vorhanden ist), aber der zweite Fall, nach Methoden zu suchen, die mit oder markiert sind Arbeit auf eine bestimmte Art und Weise ist immer noch üblich.
Update von einem Kommentar:
quelle
Method
,Constructor
,Modifier
,Field
,Member
, im Grunde scheinbar alle außerClass
) sind imjava.lang.*reflect*
Paket. Vielleicht umfasst das Konzept "Reflexion" sowohl "Typ-Introspektion" als auch Modifikation zur Laufzeit umfassend?Beispielsweise verfügen alle Objekte in Java über die Methode
getClass()
, mit der Sie die Klasse des Objekts bestimmen können, auch wenn Sie sie zur Kompilierungszeit nicht kennen (z. B. wenn Sie sie als deklariert habenObject
). Dies mag trivial erscheinen, eine solche Reflexion ist jedoch nicht möglich in weniger dynamischen Sprachen wieC++
. Mit erweiterten Anwendungen können Sie Methoden, Konstruktoren usw. auflisten und aufrufen.Reflexion ist wichtig, da Sie damit Programme schreiben können, die zur Kompilierungszeit nicht alles "wissen" müssen, wodurch sie dynamischer werden, da sie zur Laufzeit miteinander verknüpft werden können. Der Code kann gegen bekannte Schnittstellen geschrieben werden, aber die tatsächlich zu verwendenden Klassen können mithilfe der Reflektion aus Konfigurationsdateien instanziiert werden.
Viele moderne Frameworks verwenden aus diesem Grund häufig Reflexion. Die meisten anderen modernen Sprachen verwenden ebenfalls Reflektion und sind in Skriptsprachen (wie Python) noch enger integriert, da sie sich im allgemeinen Programmiermodell dieser Sprachen natürlicher anfühlen.
quelle
C++
enthält Informationen zum Laufzeit-Typ. RTTIEine meiner Lieblingsanwendungen der Reflexion ist die folgende Java-Dump-Methode. Es nimmt jedes Objekt als Parameter und verwendet die Java Reflection API, um jeden Feldnamen und Wert auszudrucken.
quelle
callCount
sollte auf Null gesetzt werden. Der Wert wird verwendet, um zu bestimmen, wie viele Registerkarten vor jeder Ausgabezeile stehen sollen: Jedes Mal, wenn ein Dump ein "Unterobjekt" ausgeben muss, wird die Ausgabe als im übergeordneten Element verschachtelt gedruckt. Diese Methode erweist sich als nützlich, wenn sie in eine andere eingewickelt wird. Überlegen SieprintDump(Object obj){ System.out.println(dump(obj, 0)); }
.Verwendung der Reflexion
Reflection wird häufig von Programmen verwendet, die die Fähigkeit benötigen, das Laufzeitverhalten von Anwendungen zu untersuchen oder zu ändern, die auf der virtuellen Java-Maschine ausgeführt werden. Dies ist eine relativ fortgeschrittene Funktion und sollte nur von Entwicklern verwendet werden, die die Grundlagen der Sprache gut verstehen. In Anbetracht dieser Einschränkung ist die Reflexion eine leistungsstarke Technik und kann es Anwendungen ermöglichen, Operationen auszuführen, die sonst unmöglich wären.
Erweiterungsfunktionen
Eine Anwendung kann externe, benutzerdefinierte Klassen verwenden, indem Instanzen von Erweiterungsobjekten unter Verwendung ihrer vollständig qualifizierten Namen erstellt werden. Klassenbrowser und visuelle Entwicklungsumgebungen Ein Klassenbrowser muss in der Lage sein, die Mitglieder von Klassen aufzulisten. Visuelle Entwicklungsumgebungen können von der Verwendung von Typinformationen profitieren, die in Reflection verfügbar sind, um dem Entwickler das Schreiben von korrektem Code zu erleichtern. Debugger und Testtools Debugger müssen in der Lage sein, private Mitglieder in Klassen zu untersuchen. Test-Harnesses können mithilfe von Reflection systematisch auffindbare Set-APIs aufrufen, die für eine Klasse definiert sind, um eine hohe Codeabdeckung in einer Testsuite sicherzustellen.
Nachteile der Reflexion
Reflexion ist stark, sollte aber nicht wahllos verwendet werden. Wenn es möglich ist, eine Operation ohne Reflexion durchzuführen, ist es vorzuziehen, sie nicht zu verwenden. Die folgenden Bedenken sollten beim Zugriff auf Code über Reflection berücksichtigt werden.
Da es sich bei der Reflektion um Typen handelt, die dynamisch aufgelöst werden, können bestimmte Optimierungen der Java Virtual Machine nicht durchgeführt werden. Folglich haben reflektierende Operationen eine langsamere Leistung als ihre nicht reflektierenden Gegenstücke und sollten in Codeabschnitten vermieden werden, die in leistungsempfindlichen Anwendungen häufig aufgerufen werden.
Für die Reflexion ist eine Laufzeitberechtigung erforderlich, die möglicherweise nicht vorhanden ist, wenn sie unter einem Sicherheitsmanager ausgeführt wird. Dies ist eine wichtige Überlegung für Code, der in einem eingeschränkten Sicherheitskontext ausgeführt werden muss, z. B. in einem Applet.
Da durch Reflexion Code Vorgänge ausführen kann, die in nicht reflektierendem Code unzulässig sind, z. B. der Zugriff auf private Felder und Methoden, kann die Verwendung von Reflexion zu unerwarteten Nebenwirkungen führen, die den Code möglicherweise funktionsunfähig machen und die Portabilität zerstören. Reflektierender Code unterbricht Abstraktionen und kann daher das Verhalten bei Upgrades der Plattform ändern.
Quelle: Die Reflection-API
quelle
Reflexion ist ein Schlüsselmechanismus, mit dem eine Anwendung oder ein Framework mit Code arbeiten kann, der möglicherweise noch nicht einmal geschrieben wurde!
Nehmen Sie zum Beispiel Ihre typische web.xml-Datei. Dies enthält eine Liste von Servlet-Elementen, die verschachtelte Servlet-Klassenelemente enthalten. Der Servlet-Container verarbeitet die Datei web.xml und erstellt durch Reflektion eine neue Instanz jeder Servlet-Klasse.
Ein weiteres Beispiel wäre die Java-API für XML-Parsing (JAXP) . Wenn ein XML-Parser-Anbieter über bekannte Systemeigenschaften 'eingesteckt' wird, die zum Erstellen neuer Instanzen durch Reflektion verwendet werden.
Und schließlich ist das umfassendste Beispiel Spring , das Reflexion verwendet, um seine Bohnen zu erstellen, und für die starke Verwendung von Proxys
quelle
Nicht jede Sprache unterstützt die Reflexion, aber die Prinzipien sind in den Sprachen, die sie unterstützen, normalerweise dieselben.
Reflexion ist die Fähigkeit, die Struktur Ihres Programms zu "reflektieren". Oder konkreter. Um die vorhandenen Objekte und Klassen zu betrachten und programmgesteuert Informationen zu den von ihnen implementierten Methoden, Feldern und Schnittstellen zurückzugewinnen. Sie können sich auch Dinge wie Anmerkungen ansehen.
Es ist in vielen Situationen nützlich. Überall, wo Sie Klassen dynamisch in Ihren Code einbinden möchten. Viele objektrelationale Mapper verwenden Reflektion, um Objekte aus Datenbanken instanziieren zu können, ohne vorher zu wissen, welche Objekte sie verwenden werden. Plug-in-Architekturen sind ein weiterer Ort, an dem Reflexion nützlich ist. In solchen Situationen ist es wichtig, Code dynamisch laden und feststellen zu können, ob es Typen gibt, die die richtige Schnittstelle für die Verwendung als Plugin implementieren.
quelle
Die Reflexion ermöglicht die Instanziierung neuer Objekte, den Aufruf von Methoden und das dynamische Abrufen / Festlegen von Operationen für Klassenvariablen zur Laufzeit, ohne dass zuvor Kenntnisse über deren Implementierung vorliegen.
Im obigen Beispiel ist der Parameter null das Objekt, für das Sie die Methode aufrufen möchten. Wenn die Methode statisch ist, geben Sie null an. Wenn die Methode nicht statisch ist, müssen Sie beim Aufrufen eine gültige MyObject-Instanz anstelle von null angeben.
Mit Reflection können Sie auch auf private Mitglieder / Methoden einer Klasse zugreifen:
.
java.lang.reflect
) nicht importieren . Auf Klassenmetadaten kann über zugegriffen werdenjava.lang.Class
.Reflection ist eine sehr leistungsfähige API, kann jedoch die Anwendung verlangsamen, wenn sie übermäßig verwendet wird, da alle Typen zur Laufzeit aufgelöst werden.
quelle
Java Reflection ist sehr leistungsfähig und kann sehr nützlich sein. Java Reflection macht es möglich Klassen, Schnittstellen, Felder und Methoden zur Laufzeit überprüft werden, ohne die Namen der Klassen, Methoden usw. zur Kompilierungszeit zu kennen. Es ist auch möglich, neue Objekte zu instanziieren, Methoden aufzurufen und Feldwerte mithilfe von Reflektion abzurufen / festzulegen.
Ein kurzes Java Reflection-Beispiel zeigt Ihnen, wie die Verwendung von Reflection aussieht:
In diesem Beispiel wird das Class-Objekt aus der Klasse MyObject abgerufen. Mit dem Klassenobjekt erhält das Beispiel eine Liste der Methoden in dieser Klasse, iteriert die Methoden und druckt ihre Namen aus.
Wie das alles genau funktioniert, wird hier erklärt
Bearbeiten : Nach fast 1 Jahr bearbeite ich diese Antwort, da ich beim Lesen über Reflexion nur noch wenige Anwendungen von Reflexion habe.
Wenn der Spring-Kontext dieses <Bean> -Element verarbeitet, verwendet er Class.forName (String) mit dem Argument "com.example.Foo", um diese Klasse zu instanziieren.
Anschließend wird die Reflektion erneut verwendet, um den entsprechenden Setter für das <Eigenschaft> -Element abzurufen und seinen Wert auf den angegebenen Wert zu setzen.
Für private Methoden
Für private Felder,
quelle
Beispiel:
Nehmen Sie zum Beispiel eine Remote-Anwendung, die Ihrer Anwendung ein Objekt gibt, das Sie mithilfe ihrer API-Methoden erhalten. Basierend auf dem Objekt müssen Sie möglicherweise eine Berechnung durchführen.
Der Anbieter garantiert, dass das Objekt drei Typen haben kann und wir eine Berechnung basierend auf dem Objekttyp durchführen müssen.
Daher können wir in 3 Klassen implementieren, die jeweils eine andere Logik enthalten. Offensichtlich sind die Objektinformationen zur Laufzeit verfügbar, sodass Sie für die Berechnung keinen statischen Code erstellen können. Daher wird die Reflexion verwendet, um das Objekt der Klasse zu instanziieren, das Sie zur Durchführung der Berechnung auf der Grundlage der Objekt vom Anbieter erhalten.
quelle
instanceof
den Objekttyp nicht zur Laufzeit bestimmen?Einfaches Beispiel für Reflexion. In einem Schachspiel wissen Sie nicht, was der Benutzer zur Laufzeit bewegt. Mit Reflection können Methoden aufgerufen werden, die bereits zur Laufzeit implementiert sind:
quelle
Reflection ist eine API, mit der das Verhalten von Methoden, Klassen und Schnittstellen zur Laufzeit untersucht oder geändert wird .
java.lang.reflect package
.Die Pakete
java.lang
undjava.lang.reflect
bieten Klassen für die Java-Reflexion.Reflexion kann verwendet werden, um Informationen über - zu erhalten
Klasse Die
getClass()
Methode wird verwendet, um den Namen der Klasse abzurufen, zu der ein Objekt gehört.Konstruktoren Mit dieser
getConstructors()
Methode werden die öffentlichen Konstruktoren der Klasse abgerufen, zu der ein Objekt gehört.Methoden Die
getMethods()
Methode wird verwendet, um die öffentlichen Methoden der Klasse abzurufen, zu der ein Objekt gehört.Die Reflection-API wird hauptsächlich verwendet in:
IDE (Integrated Development Environment), z. B. Eclipse, MyEclipse, NetBeans usw.
Debugger- und Testtools usw.
Vorteile der Verwendung von Reflexion:
Erweiterungsfunktionen: Eine Anwendung kann externe, benutzerdefinierte Klassen verwenden, indem Instanzen von Erweiterungsobjekten unter Verwendung ihrer vollständig qualifizierten Namen erstellt werden.
Debugging- und Testtools: Debugger verwenden die Eigenschaft der Reflektion, um private Mitglieder in Klassen zu untersuchen.
Nachteile:
Leistungsaufwand: Reflektierende Vorgänge weisen eine langsamere Leistung auf als nicht reflektierende Vorgänge und sollten in Codeabschnitten vermieden werden, die in leistungsempfindlichen Anwendungen häufig aufgerufen werden.
Belichtung von Interna: Reflektierender Code unterbricht Abstraktionen und kann daher das Verhalten bei Upgrades der Plattform ändern.
Ref: Java Reflection javarevisited.blogspot.in
quelle
Nach meinem Verständnis:
Durch Reflexion kann der Programmierer dynamisch auf Entitäten im Programm zugreifen. Wenn der Programmierer beim Codieren einer Anwendung keine Kenntnis von einer Klasse oder ihren Methoden hat, kann er diese Klasse dynamisch (zur Laufzeit) mithilfe von Reflection verwenden.
Es wird häufig in Szenarien verwendet, in denen sich ein Klassenname häufig ändert. Wenn eine solche Situation auftritt, ist es für den Programmierer kompliziert, die Anwendung neu zu schreiben und den Namen der Klasse immer wieder zu ändern.
Stattdessen muss durch die Verwendung von Reflection über einen sich möglicherweise ändernden Klassennamen nachgedacht werden.
quelle
Reflection ist eine Reihe von Funktionen, mit denen Sie auf die Laufzeitinformationen Ihres Programms zugreifen und dessen Verhalten ändern können (mit einigen Einschränkungen).
Dies ist nützlich, da Sie damit das Laufzeitverhalten in Abhängigkeit von den Metainformationen Ihres Programms ändern können. Sie können also den Rückgabetyp einer Funktion überprüfen und die Art und Weise ändern, wie Sie mit der Situation umgehen.
In C # können Sie beispielsweise eine Assembly (eine DLL) zur Laufzeit laden und untersuchen, durch die Klassen navigieren und die entsprechenden Aktionen ausführen. Außerdem können Sie zur Laufzeit eine Instanz einer Klasse erstellen, ihre Methode aufrufen usw.
Wo kann es nützlich sein? Ist nicht jedes Mal nützlich, aber für konkrete Situationen. Sie können es beispielsweise verwenden, um den Namen der Klasse für Protokollierungszwecke abzurufen, Handler für Ereignisse dynamisch gemäß den Angaben in einer Konfigurationsdatei zu erstellen usw.
quelle
Ich möchte nur einen Punkt zu allem hinzufügen, was aufgelistet wurde.
Mit der Reflection-API können Sie eine universelle
toString()
Methode für jedes Objekt schreiben .Es ist nützlich beim Debuggen.
Hier ist ein Beispiel:
quelle
Reflexion besteht darin, das Objekt sein Aussehen sehen zu lassen. Dieses Argument scheint nichts mit Reflexion zu tun zu haben. In der Tat ist dies die Fähigkeit, sich selbst zu identifizieren.
Reflexion selbst ist ein Wort für solche Sprachen, denen die Fähigkeit zur Selbsterkenntnis und Selbsterkenntnis fehlt, wie Java und C #. Da sie nicht die Fähigkeit zur Selbsterkenntnis haben, müssen wir, wenn wir beobachten wollen, wie es aussieht, etwas anderes haben, um darüber nachzudenken, wie es aussieht. Hervorragende dynamische Sprachen wie Ruby und Python können die Reflexion ihrer eigenen Sprache ohne die Hilfe anderer Personen wahrnehmen. Wir können sagen, dass das Objekt von Java nicht erkennen kann, wie es ohne einen Spiegel aussieht, der ein Objekt der Reflexionsklasse ist, aber ein Objekt in Python kann es ohne einen Spiegel wahrnehmen. Deshalb brauchen wir Reflexion in Java.
quelle
Von Java - Dokumentation Seite
AccessibleObject
ermöglicht die Unterdrückung von Zugriffsprüfungen, wenn die erforderlichenReflectPermission
verfügbar sind.Klassen in diesem Paket sowie
java.lang.Class
Anwendungen wie Debugger, Interpreter, Objektinspektoren, Klassenbrowser und Dienste wieObject Serialization
undJavaBeans
, die Zugriff auf die öffentlichen Mitglieder eines Zielobjekts (basierend auf seiner Laufzeitklasse) oder die von deklarierten Mitglieder benötigen eine bestimmte KlasseEs enthält folgende Funktionen.
In diesem Dokumentationslink finden Sie Informationen zu den von der
Class
Klasse bereitgestellten Methoden .Aus diesem Artikel (von Dennis Sosnoski, Präsident von Sosnoski Software Solutions, Inc) und diesem Artikel (Sicherheitsuntersuchungen pdf):
Ich sehe erhebliche Nachteile als die Verwendung von Reflection
Benutzer der Reflexion:
Nachteile der Reflexion:
Allgemeiner Missbrauch:
Schauen Sie sich diese SE-Frage zum Missbrauch der Reflexionsfunktion an:
Wie lese ich ein privates Feld in Java?
Zusammenfassung:
Unsichere Nutzung ihrer Funktionen innerhalb eines Systems Code durchgeführt kann auch führen leicht auf den Kompromiss eines Java - Sicherheitsmodus l. Verwenden Sie diese Funktion daher sparsam
quelle
Woozle
beim Start andere Klassen untersuchen zu lassen, um festzustellen, welche über eine statischeRegisterAsWoozleHelper()
Methode verfügen , und alle gefundenen Methoden mit einem Rückruf aufzurufen, mit dem sieWoozle
über sich selbst berichten können, um dies zu vermeiden müssen Reflection verwenden, während z. B. Daten deserialisiert werden.Wie der Name selbst andeutet, spiegelt er das wider, was er beispielsweise für eine Klassenmethode usw. enthält, abgesehen von der Bereitstellung einer Funktion zum dynamischen Aufrufen einer Methode, die zur Laufzeit eine Instanz erstellt.
Es wird von vielen Frameworks und Anwendungen unter dem Holz verwendet, um Dienste aufzurufen, ohne den Code tatsächlich zu kennen.
quelle
Durch Reflexion können Sie allgemeineren Code schreiben. Sie können ein Objekt zur Laufzeit erstellen und seine Methode zur Laufzeit aufrufen. Somit kann das Programm stark parametrisiert werden. Es ermöglicht auch die Introspektion des Objekts und der Klasse, um seine Variablen und Methoden zu erkennen, die der Außenwelt ausgesetzt sind.
quelle
Reflection
hat viele Verwendungszwecke . Das, mit dem ich besser vertraut bin, ist, Code im laufenden Betrieb erstellen zu können.quelle
Ich möchte diese Frage anhand eines Beispiels beantworten. Zunächst generiert das
Hibernate
Projekt Anweisungen, um die Kluft zwischen der laufenden Anwendung und dem Persistenzspeicher zu überbrücken. Wenn sich Dinge in der Domäne ändern, muss der über sie Bescheid wissen, um sie im Datenspeicher zu speichern und umgekehrt.Reflection API
CRUD
Hibernate
Alternativ funktioniert
Lombok Project
. Es wird nur Code zur Kompilierungszeit eingefügt, was dazu führt, dass Code in Ihre Domänenklassen eingefügt wird. (Ich denke, es ist OK für Getter und Setter)Hibernate
Diese Option wurde ausgewählt,reflection
da sie nur minimale Auswirkungen auf den Erstellungsprozess einer Anwendung hat.Und von Java 7 haben wir
MethodHandles
, was funktioniert alsReflection API
. In Projekten kopieren wir zum Arbeiten mit Loggern einfach den nächsten Code:Weil es in diesem Fall schwierig ist, Tippfehler zu machen.
quelle
Wie ich es am besten finde, anhand eines Beispiels zu erklären, und keine der Antworten scheint dies zu tun ...
Ein praktisches Beispiel für die Verwendung von Reflexionen wäre ein in Java geschriebener Java Language Server oder ein in PHP geschriebener PHP Language Server usw. Language Server bietet Ihren IDE-Funktionen wie Autocomplete, Sprung zur Definition, Kontexthilfe, Hinweistypen und mehr. Damit alle Tag-Namen (Wörter, die automatisch vervollständigt werden können) alle möglichen Übereinstimmungen während der Eingabe anzeigen, muss der Sprachserver alles über die Klasse überprüfen, einschließlich Dokumentblöcke und privater Mitglieder. Dafür braucht es eine Reflexion dieser Klasse.
Ein anderes Beispiel wäre ein Unit-Test einer privaten Methode. Eine Möglichkeit, dies zu tun, besteht darin, eine Reflexion zu erstellen und den Anwendungsbereich der Methode in der Einrichtungsphase des Tests öffentlich zu machen. Natürlich kann man argumentieren, dass private Methoden nicht direkt getestet werden sollten, aber das ist nicht der Punkt.
quelle