Ist es mit Java Reflection möglich, den Namen einer lokalen Variablen abzurufen? Zum Beispiel, wenn ich das habe:
Foo b = new Foo();
Foo a = new Foo();
Foo r = new Foo();
ist es möglich, eine Methode zu implementieren, die die Namen dieser Variablen finden kann, wie folgt:
public void baz(Foo... foos)
{
for (Foo foo: foos) {
// Print the name of each foo - b, a, and r
System.out.println(***);
}
}
BEARBEITEN: Diese Frage unterscheidet sich von Gibt es in Java eine Möglichkeit, den Namen der Variablen zu finden, die an eine Funktion übergeben wurde? , dass die Frage, ob man den Namen einer lokalen Variablen mithilfe von Reflexion bestimmen kann, reiner gestellt wird, während sich die andere Frage (einschließlich der akzeptierten Antwort) mehr auf das Testen von Variablenwerten konzentriert.
java
reflection
David Koelle
quelle
quelle
Antworten:
Ab Java 8 sind einige Informationen zu lokalen Variablennamen durch Reflektion verfügbar. Siehe den Abschnitt "Update" weiter unten.
Vollständige Informationen werden häufig in Klassendateien gespeichert. Eine Optimierung zur Kompilierungszeit besteht darin, sie zu entfernen, Platz zu sparen (und eine gewisse Verschleierung bereitzustellen). Wenn es jedoch vorhanden ist, verfügt jede Methode über ein Tabellenattribut für lokale Variablen, das den Typ und den Namen lokaler Variablen sowie den Befehlsbereich auflistet, in dem sie sich im Gültigkeitsbereich befinden.
Möglicherweise können Sie mit einer Bytecode-Engineering-Bibliothek wie ASM diese Informationen zur Laufzeit überprüfen. Der einzige vernünftige Ort, an den ich denken kann, um diese Informationen zu benötigen, ist ein Entwicklungstool. Daher ist das Bytecode-Engineering wahrscheinlich auch für andere Zwecke nützlich.
Update: Eingeschränkte Unterstützung für diese wurde hinzugefügt , um Java 8. Parameter (eine spezielle Klasse von lokalen Variablen) Namen sind nun über Reflexion zur Verfügung. Dies kann unter anderem dazu beitragen,
@ParameterName
Anmerkungen zu ersetzen, die von Abhängigkeitsinjektionscontainern verwendet werden.quelle
Es ist überhaupt nicht möglich. Variablennamen werden in Java nicht kommuniziert (und können aufgrund von Compiler-Optimierungen auch entfernt werden).
BEARBEITEN (im Zusammenhang mit Kommentaren):
Wenn Sie von der Idee zurücktreten, es als Funktionsparameter verwenden zu müssen, finden Sie hier eine Alternative (die ich nicht verwenden würde - siehe unten):
Es wird Probleme geben, wenn
a == b, a == r, or b == r
oder es andere Felder gibt, die dieselben Referenzen haben.BEARBEITEN jetzt unnötig, da die Frage geklärt wurde
quelle
( Bearbeiten: Zwei vorherige Antworten wurden entfernt, eine für die Beantwortung der Frage, wie sie vor der Bearbeitung stand, und eine, um, wenn nicht absolut falsch, zumindest nahe daran zu sein. )
Wenn Sie mit Debug-Informationen zu (
javac -g
) kompilieren , werden die Namen lokaler Variablen in der .class-Datei gespeichert. Nehmen Sie zum Beispiel diese einfache Klasse:Nach dem Kompilieren mit befinden
javac -g:vars TestLocalVarNames.java
sich die Namen der lokalen Variablen jetzt in der .class-Datei.javap
Das-l
Flag ("Zeilennummer und lokale Variablentabellen drucken") kann sie anzeigen.javap -l -c TestLocalVarNames
zeigt an:Die VM-Spezifikation erklärt, was wir hier sehen:
§4.7.9 Das
LocalVariableTable
Attribut :Das
LocalVariableTable
speichert die Namen und Typen der Variablen in jedem Slot, so dass es möglich ist, sie mit dem Bytecode abzugleichen. Auf diese Weise können Debugger "Ausdruck auswerten" ausführen.Wie erickson sagte, gibt es jedoch keine Möglichkeit, durch normale Reflexion auf diese Tabelle zuzugreifen. Wenn Sie immer noch entschlossen sind, dies zu tun, wird die Java Platform Debugger Architecture (JPDA) meiner Meinung nach helfen (aber ich habe sie selbst nie verwendet).
quelle
javac
für jede Methode eine lokale Variablentabelle in die Klasse eingefügt, um das Debuggen zu unterstützen. Verwenden Sie die-l
Option,javap
um die lokale Variablentabelle anzuzeigen.javac -g:vars
, um es zu bekommen. (Ich habe in den letzten drei Stunden versucht, diese Antwort zu bearbeiten, aber wie gesagt, meine Netzwerkverbindung hat Probleme, was die Recherche schwierig macht.)quelle
getDeclaredFields()
kann verwendet werden, wenn Sie auch die Namen von privaten Feldern möchtenSie können dies tun:
quelle
Alles, was Sie tun müssen, ist, ein Array von Feldern zu erstellen und es dann auf die gewünschte Klasse zu setzen, wie unten gezeigt.
Zum Beispiel, wenn Sie es getan haben
du würdest bekommen
quelle
Aktualisieren Sie die Antwort von @Marcel Jackwerth für allgemein.
und nur mit Klassenattributen arbeiten, nicht mit Methodenvariablen.
quelle
siehe dieses Beispiel:
quelle