Java Reflection: How to get the name of a variable?
Отражение Java: как получить имя переменной?
Используя отражение Java, возможно ли получить имя локальной переменной? Например, если у меня есть это:
Foob=newFoo(); Fooa=newFoo(); Foor=newFoo();
возможно ли реализовать метод, который может находить имена этих переменных, например:
publicvoidbaz(Foo... foos) { for (Foo foo: foos) { // Print the name of each foo - b, a, and r System.out.println(***); } }
РЕДАКТИРОВАТЬ: Этот вопрос отличается от Есть ли в Java способ найти имя переменной, которая была передана функции? в том смысле, что оно более чисто задает вопрос о том, можно ли использовать отражение для определения имени локальной переменной, тогда как другой вопрос (включая принятый ответ) больше ориентирован на тестирование значений переменных.
Переведено автоматически
Ответ 1
Начиная с Java 8, некоторая информация об именах локальных переменных доступна через отражение. Смотрите раздел "Обновление" ниже.
Полная информация часто хранится в файлах классов. Одна из оптимизаций во время компиляции заключается в ее удалении, что экономит место (и обеспечивает некоторую запутанность). Однако, когда оно присутствует, каждый метод имеет атрибут таблицы локальных переменных, в котором перечислены тип и имя локальных переменных, а также диапазон инструкций, в которых они находятся в области видимости.
Возможно, инженерная библиотека байт-кода, такая как ASM, позволила бы вам проверять эту информацию во время выполнения. Единственное разумное место, которое я могу придумать для получения этой информации, - это инструмент разработки, и поэтому разработка байт-кода, вероятно, будет полезна и для других целей.
Обновление: В Java 8 была добавлена ограниченная поддержка для этого. Имена параметров (особый класс локальных переменных) теперь доступны через отражение. Среди прочих целей это может помочь заменить @ParameterName аннотации, используемые контейнерами внедрения зависимостей.
Ответ 2
Это вообще невозможно. Имена переменных не передаются в Java (и также могут быть удалены из-за оптимизации компилятора).
РЕДАКТИРОВАТЬ (связано с комментариями):
Если вы откажетесь от идеи использования ее в качестве параметров функции, вот альтернатива (которую я бы не стал использовать - см. Ниже):
Возникнут проблемы, если a == b, a == r, or b == r или есть другие поля, которые имеют те же ссылки.
РЕДАКТИРОВАТЬ теперь не нужно, поскольку вопрос прояснен
Ответ 3
(Редактировать: удалены два предыдущих ответа, один за то, что он отвечал на вопрос в том виде, в котором он стоял до внесения изменений, и один за то, что он был если не абсолютно неправильным, то, по крайней мере, близким к нему.)
Если вы компилируете с отладочной информацией в (javac -g), имена локальных переменных сохраняются в файле .class. Например, возьмем этот простой класс:
После компиляции с помощью javac -g:vars TestLocalVarNames.java имена локальных переменных теперь находятся в файле .class. Флаг javap's -l ("Напечатать номер строки и таблицы локальных переменных") может их отображать.
LocalVariableTable Атрибут является необязательным атрибутом переменной длины для Code (§4.7.3) атрибута. Оно может использоваться отладчиками для определения значения данной локальной переменной во время выполнения метода.
В LocalVariableTable хранятся имена и типы переменных в каждом слоте, поэтому их можно сопоставить с байт-кодом. Именно так отладчики могут выполнять "Вычисление выражения".
Однако, как сказал Эриксон, нет способа получить доступ к этой таблице через обычное отражение. Если вы все еще полны решимости сделать это, я верю, что архитектура отладчика платформы Java (JPDA) поможет (но я сам никогда ею не пользовался).