Ich bin neu in Java. Während meines Studiums habe ich gelesen, dass Reflexion verwendet wird, um Klassen und Methoden aufzurufen und um zu wissen, welche Methoden implementiert sind oder nicht.
Wann sollte ich Reflection verwenden, und was ist der Unterschied zwischen der Verwendung von Reflection und der Instanziierung von Objekten und dem herkömmlichen Aufrufen von Methoden?
java
reflection
Hamzah Khammash
quelle
quelle
Antworten:
Reflexion ist viel langsamer als nur das Aufrufen von Methoden mit ihrem Namen, da die Metadaten im Bytecode überprüft werden müssen, anstatt nur vorkompilierte Adressen und Konstanten zu verwenden.
Reflexion ist auch leistungsfähiger: Sie ist die Definition eines abrufen kann
protected
oderfinal
Mitglied, entfernen Sie den Schutz und manipulieren, als ob es wandelbar erklärt worden war! Offensichtlich untergräbt dies viele der Garantien, die die Sprache normalerweise für Ihre Programme bietet, und kann sehr, sehr gefährlich sein.Und das erklärt ziemlich genau, wann man es benutzt. Normalerweise nicht. Wenn Sie eine Methode aufrufen möchten, rufen Sie sie einfach auf. Wenn Sie ein Mitglied mutieren möchten, deklarieren Sie es einfach als mutierbar, anstatt hinter den Rücken des Compilers zu gehen.
Eine nützliche Anwendung der Reflexion in der Praxis ist das Schreiben eines Frameworks, das mit benutzerdefinierten Klassen zusammenarbeiten muss, wobei der Framework-Autor nicht weiß, was die Mitglieder (oder sogar die Klassen) sein werden. Reflexion ermöglicht es ihnen, mit jeder Klasse umzugehen, ohne es vorher zu wissen. Ich glaube zum Beispiel nicht, dass es möglich wäre, eine komplexe aspektorientierte Bibliothek ohne Reflexion zu schreiben.
Als weiteres Beispiel verwendete JUnit ein triviales Spiegelbild: Es listet alle Methoden in Ihrer Klasse auf, nimmt an, dass alle aufgerufenen
testXXX
Methoden Testmethoden sind, und führt nur diese aus. Dies kann jetzt jedoch besser mit Anmerkungen geschehen, und tatsächlich wurde JUnit 4 größtenteils auf Anmerkungen umgestellt.quelle
Ich war wie du einmal, ich wusste nicht viel über Reflexion - weiß es immer noch nicht - aber ich habe es einmal benutzt.
Ich hatte eine Klasse mit zwei inneren Klassen und jede Klasse hatte viele Methoden.
Ich musste alle Methoden in der inneren Klasse aufrufen, und das manuelle Aufrufen wäre zu aufwendig gewesen.
Mit Reflection konnte ich alle diese Methoden in nur 2-3 Codezeilen anstelle der Anzahl der Methoden selbst aufrufen.
quelle
Ich würde die Verwendung von Reflexion in drei Gruppen einteilen:
quelle
Reflection ermöglicht es einem Programm, mit Code zu arbeiten, der möglicherweise nicht vorhanden ist, und dies auf zuverlässige Weise.
"Normaler Code" hat Snippets,
URLConnection c = null
die durch ihr Vorhandensein dazu führen, dass der Klassenlader die URLConnection-Klasse als Teil des Ladens dieser Klasse lädt, eine ClassNotFound-Ausnahme auslöst und beendet.Mit Reflection können Sie Klassen basierend auf ihren Namen in Zeichenfolgenform laden und auf verschiedene Eigenschaften testen (nützlich für mehrere Versionen außerhalb Ihres Steuerelements), bevor Sie tatsächliche Klassen starten, die von ihnen abhängen. Ein typisches Beispiel ist der OS X-spezifische Code, der verwendet wird, um Java-Programme unter OS X nativ erscheinen zu lassen, die auf anderen Plattformen nicht vorhanden sind.
quelle
Reflektion bedeutet grundsätzlich, den Code Ihres Programms als Daten zu verwenden.
Daher ist die Verwendung von Reflection möglicherweise eine gute Idee, wenn der Code Ihres Programms eine nützliche Datenquelle ist. (Aber es gibt Kompromisse, daher ist es möglicherweise nicht immer eine gute Idee.)
Stellen Sie sich zum Beispiel eine einfache Klasse vor:
und Sie möchten XML daraus generieren. Sie könnten Code schreiben, um das XML zu generieren:
Dies ist jedoch eine Menge Boilerplate-Code, und jedes Mal, wenn Sie die Klasse ändern, müssen Sie den Code aktualisieren. Wirklich, Sie könnten beschreiben, wie dieser Code funktioniert
Dies ist ein Algorithmus, und die Eingabe des Algorithmus ist die Klasse: Wir benötigen seinen Namen und die Namen, Typen und Werte seiner Eigenschaften. Hier kommt die Reflexion ins Spiel: Sie verschafft Ihnen Zugang zu diesen Informationen. Mit Java können Sie Typen mit den Methoden der
Class
Klasse untersuchen.Einige weitere Anwendungsfälle:
Vollständige Reflexion bedeutet jedoch nicht nur, vorhandenen Code (der an sich als "Introspektion" bezeichnet wird) zu betrachten, sondern auch Code zu ändern oder zu generieren. Hierfür gibt es in Java zwei wichtige Anwendungsfälle: Proxies und Mocks.
Angenommen, Sie haben eine Schnittstelle:
und Sie haben eine Implementierung, die etwas Interessantes bewirkt:
Und tatsächlich haben Sie auch eine zweite Implementierung:
Jetzt möchten Sie auch eine Protokollausgabe; Sie möchten einfach eine Protokollnachricht, wenn eine Methode aufgerufen wird. Sie könnten jeder Methode explizit eine Protokollausgabe hinzufügen, aber das wäre ärgerlich, und Sie müssten es zweimal tun. einmal für jede Implementierung. (Umso mehr, wenn Sie weitere Implementierungen hinzufügen.)
Stattdessen können Sie einen Proxy schreiben:
Wieder gibt es jedoch ein sich wiederholendes Muster, das durch einen Algorithmus beschrieben werden kann:
und die Eingabe dieses Algorithmus ist die Schnittstellendefinition.
Mit Reflection können Sie mit diesem Algorithmus eine neue Klasse definieren. Mit Java können Sie dies mit den Methoden der
java.lang.reflect.Proxy
Klasse tun , und es gibt Bibliotheken, die Ihnen noch mehr Leistung bieten.Was sind die Nachteile der Reflexion?
quelle
Mit Reflection können Teile Ihres Programms automatisch synchronisiert werden. Bisher mussten Sie Ihr Programm manuell aktualisieren, um die neuen Benutzeroberflächen zu verwenden.
quelle