Czy za pomocą Java Reflection można uzyskać nazwę zmiennej lokalnej? Na przykład, jeśli mam to:
Foo b = new Foo();
Foo a = new Foo();
Foo r = new Foo();
czy można zaimplementować metodę, która może znaleźć nazwy tych zmiennych, na przykład:
public void baz(Foo... foos)
{
for (Foo foo: foos) {
// Print the name of each foo - b, a, and r
System.out.println(***);
}
}
EDYCJA: To pytanie różni się od Czy w Javie istnieje sposób na znalezienie nazwy zmiennej, która została przekazana do funkcji? w tym, że bardziej czysto stawia pytanie, czy można użyć refleksji do określenia nazwy zmiennej lokalnej, podczas gdy drugie pytanie (w tym przyjęta odpowiedź) jest bardziej ukierunkowane na testowanie wartości zmiennych.
java
reflection
David Koelle
źródło
źródło
Odpowiedzi:
Począwszy od wersji Java 8, niektóre informacje o nazwach zmiennych lokalnych są dostępne poprzez odbicie. Zobacz sekcję „Aktualizacja” poniżej.
Pełne informacje są często przechowywane w plikach zajęć. Jedną z optymalizacji czasu kompilacji jest usunięcie go, oszczędzając miejsce (i zapewniając pewne zaciemnienie). Jednak gdy jest obecny, każda metoda ma atrybut tabeli zmiennych lokalnych, który zawiera typ i nazwę zmiennych lokalnych oraz zakres instrukcji, w których są one objęte.
Być może biblioteka inżynierii kodu bajtowego, taka jak ASM , pozwoliłaby na wgląd w te informacje w czasie wykonywania. Jedynym rozsądnym miejscem, w którym potrzebuję tych informacji, jest narzędzie programistyczne, więc inżynieria kodu bajtowego może być przydatna również do innych celów.
Aktualizacja: Ograniczona obsługa tego została dodana do języka Java 8. Nazwy parametrów (specjalna klasa zmiennych lokalnych) są teraz dostępne poprzez odbicie. Może to między innymi pomóc w zastąpieniu
@ParameterName
adnotacji używanych przez kontenery iniekcji zależności.źródło
W ogóle nie jest to możliwe. Nazwy zmiennych nie są przekazywane w Javie (i mogą zostać usunięte z powodu optymalizacji kompilatora).
EDYCJA (dotyczy komentarzy):
Jeśli wycofasz się z pomysłu używania go jako parametrów funkcji, oto alternatywa (której nie użyłbym - patrz poniżej):
Będą problemy, jeśli
a == b, a == r, or b == r
istnieją inne pola, które mają te same odniesienia.EDYCJA jest teraz niepotrzebna, ponieważ pytanie zostało wyjaśnione
źródło
( Edycja: usunięto dwie poprzednie odpowiedzi, jedną za udzielenie odpowiedzi na pytanie przed edycją, a drugą za bycie, jeśli nie absolutnie błędne, to przynajmniej blisko tego. )
Jeśli kompilujesz z informacjami debugowania w (
javac -g
), nazwy zmiennych lokalnych są przechowywane w pliku .class. Weźmy na przykład tę prostą klasę:Po skompilowaniu z
javac -g:vars TestLocalVarNames.java
, nazwy zmiennych lokalnych znajdują się teraz w pliku .class.javap
„s-l
flag («Broszura numer linii i lokalnych tabel zmienna») może je pokazać.javap -l -c TestLocalVarNames
przedstawia:Specyfikacja maszyny wirtualnej wyjaśnia, co tu widzimy:
§4.7.9
LocalVariableTable
Atrybut :W
LocalVariableTable
sklepach nazwy i typy zmiennych w każdej szczelinie, więc możliwe jest, aby dopasować je do kodu bajtowego z. W ten sposób debugery mogą wykonywać „Obliczanie wyrażenia”.Jednak, jak powiedział Erickson, nie ma sposobu, aby uzyskać dostęp do tego stołu poprzez normalną refleksję. Jeśli nadal jesteś zdeterminowany, aby to zrobić, uważam, że architektura debugera platformy Java (JPDA) pomoże (ale nigdy jej nie używałem).
źródło
javac
umieszcza lokalną tabelę zmiennych w klasie dla każdej metody, aby ułatwić debugowanie. Użyj-l
opcji, abyjavap
wyświetlić lokalną tabelę zmiennych.javac -g:vars
go zdobyć. (Próbowałem edytować tę odpowiedź przez ostatnie trzy godziny, ale jak powiedziałem, moje połączenie sieciowe ma problemy, co utrudnia badanie.)źródło
getDeclaredFields()
można użyć w przypadku, gdy chcesz również nazwy prywatnych pólMożesz zrobić tak:
źródło
Wszystko, co musisz zrobić, to utworzyć tablicę pól, a następnie ustawić ją na żądaną klasę, jak pokazano poniżej.
Na przykład, jeśli tak
dostaniesz
źródło
zaktualizuj odpowiedź @Marcel Jackwerth dla generała.
i działa tylko z atrybutem klasy, nie działa ze zmienną metody.
źródło
zobacz ten przykład:
źródło