Отражение Java: как получить имя переменной?
используя отражение Java, можно ли получить имя локальной переменной? Например, если у меня есть это:
можно ли реализовать метод, который может найти имена этих переменных, например, так:
EDIT: этот вопрос отличается от того, есть ли способ в Java найти имя переменной, которая была передана функции? в том, что это более чисто задает вопрос о том, можно ли использовать отражение, чтобы определить имя локальная переменная, тогда как другой вопрос (включая принятый ответ) больше ориентирован на тестирование значений переменных.
7 ответов:
начиная с Java 8, некоторая информация об имени локальной переменной доступна через отражение. Смотрите «обновить» ниже.
полная информация часто хранится в файлах классов. Одна оптимизация времени компиляции заключается в ее удалении, экономии места (и обеспечении некоторой обсфускации). Однако, когда он присутствует, каждый метод имеет атрибут таблицы локальных переменных, в котором перечислены тип и имя локальных переменных, а также диапазон инструкций, в которых они находятся масштаб.
возможно, байт-код инженерной библиотеки, как ПКР позволит вам проверить эту информацию во время выполнения. Единственное разумное место, которое я могу придумать для необходимости этой информации,-это инструмент разработки, и поэтому разработка байтового кода, вероятно, будет полезна и для других целей.
обновление: ограниченная поддержка для этого был добавлено в Java 8. параметр (специальный класс локальной переменной) имена теперь доступный через отражение. Среди других целей, это может помочь заменить @ParameterName аннотации, используемые контейнерами инъекций зависимостей.
Это не возможно. Имена переменных не передаются в Java (а также могут быть удалены из-за оптимизации компилятора).
редактировать (связанные с комментариями):
Если вы отступите от идеи использовать его в качестве параметров функции, вот альтернатива (которую я бы не использовал-см. ниже):
будут проблемы, если a == b, a == r, or b == r или есть другие поля, которые имеют тот же ссылки на литературу.
редактировать теперь не нужно, так как вопрос прояснился
(Edit: два предыдущих ответа удалены, один для ответа на вопрос, как он стоял перед редактированием, и один для того, чтобы быть, если не абсолютно неправильным, по крайней мере, близко к нему.)
если вы компилируете с отладочной информацией на ( javac -g ), имена локальных переменных сохраняются в поле .файл класса. Например, возьмем такой простой класс:
после компиляции с javac -g:vars TestLocalVarNames.java имена локальных переменных сейчас .файл класса. javap ‘ s -l флаг («Номер строки печати и таблицы локальных переменных») может показать их.
javap -l -c TestLocalVarNames показывает:
The VM spec объясняет, что мы видим здесь:
The LocalVariableTable атрибут является необязательным атрибутом переменной длины Code (§4.7.3) атрибут. Он может использоваться отладчиками для определения значения заданной локальной переменной во время выполнения a метод.
The LocalVariableTable сохраняет имена и типы переменных в каждом слоте, так что можно сопоставить их с байт-кодом. Вот как отладчики могут сделать «вычислить выражение».
архитектура отладчика платформы Java (JPDA) поможет (но я никогда не использовал его сам).
Источник
Отражение Java: Как получить имя переменной?
Используя Java Reflection, возможно ли получить имя локальной переменной? Например, если у меня есть это:
возможно ли реализовать метод, который может найти имена этих переменных, например так:
РЕДАКТИРОВАТЬ. Этот вопрос отличается от Есть ли способ в Java найти имя переменной, которая была передана функции? в том, что она более чисто спрашивает вопрос о том, можно ли использовать рефлексию для определения имени локальной переменной, тогда как другой вопрос (включая принятый ответ) больше ориентирован на тестирование значений переменных.
7 ответов
Начиная с Java 8, некоторая информация об именах локальных переменных доступна через отражение. См. Раздел «Обновление» ниже.
Полная информация часто хранится в файлах классов. Одна оптимизация во время компиляции состоит в том, чтобы удалить это, экономя место (и предоставляя некоторую запутанность). Однако, когда он присутствует, у каждого метода есть атрибут таблицы локальных переменных, в котором перечислены тип и имя локальных переменных, а также диапазон инструкций, в которых они находятся.
Возможно, библиотека разработки байт-кода, такая как ASM , позволит вам проверить эту информацию во время выполнения. Единственное разумное место, где я могу найти эту информацию, — это инструмент разработки, и поэтому разработка байт-кода, вероятно, будет полезна и для других целей.
Обновление . Ограниченная поддержка для этого была добавлена в Java 8. Имена параметров (специальный класс локальных переменных) теперь доступны через отражение. Помимо прочего, это может помочь заменить аннотации @ParameterName , используемые контейнерами для внедрения зависимостей.
Это не возможно вообще. Имена переменных не передаются в Java (и могут также быть удалены из-за оптимизации компилятора).
РЕДАКТИРОВАТЬ (связано с комментариями):
Если вы отступите от идеи использования его в качестве параметров функции, вот альтернатива (которую я бы не использовал — см. ниже):
Будут проблемы, если a == b, a == r, or b == r или есть другие поля с такими же ссылками.
РЕДАКТИРОВАТЬ теперь не нужно, поскольку вопрос прояснился
( Изменить: два предыдущих ответа удалены: один для ответа на вопрос в том виде, в каком он был до редактирования, и один для того, чтобы быть, если не абсолютно ошибочным, по крайней мере близким к нему. )
Если вы компилируете с отладочной информацией ( javac -g ), имена локальных переменных сохраняются в файле .class. Например, возьмем этот простой класс:
После компиляции с помощью javac -g:vars TestLocalVarNames.java имена локальных переменных теперь находятся в файле .class. Флаг javap -l («Печать номер строки и таблицы локальных переменных «) может показать их.
javap -l -c TestLocalVarNames показывает:
В спецификации ВМ объясняется что мы видим здесь:
Атрибут LocalVariableTable является необязательным атрибутом переменной длины для Code (§4.7.3) атрибут. Он может использоваться отладчиками для определения значения заданной локальной переменной во время выполнения метода.
LocalVariableTable хранит имена и типы переменных в каждом слоте, поэтому их можно сопоставить с байт-кодом. Вот как отладчики могут выполнять «Оценивать выражение».
Однако, как сказал Эриксон, нет способа получить доступ к этой таблице с помощью обычного отражения. Если вы все еще намерены это сделать, я считаю, что Архитектура отладчика платформы Java ( JPDA) поможет (но сам никогда этим не пользовался).
Источник
Java переменные
В предыдущих уроках мы говорили о том, что класс в Java состоит из атрибутов и методов. Переменные могут быть атрибутами класса, параметрами метода или могут использоваться в программе для краткосрочного хранения данных. В языке Java все переменные должны быть объявлены, перед тем, как они будут использоваться.
Объявление переменных в java
При объявлении переменной, в следующей последовательности указываются:
- тип данных (в данном примере — int — переменная содержит целое число),
- имя переменной (в данном примере имена — x и y),
- начальное значение переменной или, другими словами, инициализация переменной. В данном примере переменным x и y присвоены значения 1 и 2. Однако, это не является обязательным условием при объявлении переменной.
Пример: объявление переменных без инициализации:
После каждой строки при объявлении переменных необходимо ставить точку с запятой «;».
Если нужно объявить несколько переменных одного типа, то это также можно сделать одной строкой, указав имена переменных через запятую.
Правила именования переменных в java
- Имя переменной должно начинаться с буквы (маленькой) и состоять из букв (Unicode) цифр и символа подчеркивания «_». Технически возможно начать имя переменной также с «$» или «_», однако это запрещено соглашением по оформлению кода в Java (Java Code Conventions). Кроме того, символ доллара «$», по соглашению, никогда не используется вообще. В соответствии с соглашением имя переменной должно начинаться именно с маленькой буквы (с заглавной буквы начинаются имена классов). Пробелы при именовании переменных не допускаются.
- Имя переменной не должно бытьключевым или зарезервированным словом языка Java.
- Имя переменной чувствительно к регистру. newVariable и newvariable — разные имена.
- При выборе имени переменных, следует использовать полные слова вместо загадочных аббревиатур. Это сделает ваш код более удобным для чтения и понимания. Во многих случаях это также сделает ваш код самодокументируемым.
- Если выбранное вами имя переменной состоит только из одного слова — запишите его маленькими буквами. Если оно состоит из более чем одного слова, то отделяйте каждое последующее слово в имени переменной заглавной буквой. Например: superCounter, myDomesticAnimal
- Если переменная сохраняет постоянное значение, то каждое слово следует писать заглавными буквами и отделять при помощи символа подчеркивания. Пример: static final int NUMBER_OF_HOURS_IN_A_DAY = 24
Типы данных в java
Каждая переменная и каждое выражение в Java обладает типом и этот тип строго определен.
Примитивные типы данных
В Java существует 8 примитивных типов данных:
- byte (целые числа, 1 байт)
- short (целые числа, 2 байта)
- int (целые числа, 4 байта)
- long (целые числа, 8 байтов)
- float (вещественные числа, 4 байта)
- double (вещественные числа, 8 байтов)
- char (символ Unicode, 2 байта)
- boolean (значение истина/ложь, 1 байт)
Эти 8 типов служат основой для всех остальных типов данных. Примитивные типы обладают явным диапазоном допустимых значений.
byte — диапазон допустимых значений от -128 до 127
Переменные типа byte полезны при работе с потоком данных, который поступает из сети или файла.
short — диапазон допустимых значений от -32768 до 32767
int — диапазон допустимых значений от -2147483648 до 2147483647
Тип int используется чаще при работе с целочисленными данными, нежели byte и short, даже если их диапазона хватает. Это происходит потому, что при указании значений типа byte и short в выражениях, их тип все равно автоматически повышается до int при вычислении.
long — диапазон допустимых значений от -9223372036854775808 до 9223372036854775807
Тип удобен для работы с большими целыми числами.
float — диапазон допустимых значений от
Удобен для использования, когда не требуется особой точности в дробной части числа.
double — диапазон допустимых значений от
Математические функции такие как sin(), cos(), sqrt() возвращают значение double
char — символьный тип данных представляет собой один 16-битный Unicode символ. Он имеет минимальное значение ‘\ u0000’ (или 0), и максимальное значение ‘\ uffff’ (или 65535 включительно). Символы char можно задавать также при помощи соответствующих чисел. Например символ ‘Ы’ соответствует числу 1067. Рассмотрим на примере:
Вывод этой программы будет:
Небольшой пример того, как узнать, какому числу соответствует символ. Основан на претиповании данных.
На выводе программа показывает, что символу 'J' соответствует число 74.
boolean — предназначен для хранения логических значений. Переменные этого типа могут принимать только одно из 2х возможных значений true или false.
Тип String
Тип String не является примитивным типом данных, однако это один из наиболее используемых типов в Java. String предназначен для хранения строк текста. Несколько примеров использования String
Для строк определен оператор «+»
Ссылочные типы данных
В ссылочные типы входят все классы, интерфейсы, массивы. Описанный выше тип String также относится к ссылочным типам. Этот класс из стандартной библиотеки Java.
Также существуют классы-оболочки:
В отличие от примитивных типов, они пишутся с заглавной буквы. Эти типы соответствуют примитивным типам, однако являются ссылочными. Их классы cодержат методы для преобразования типов, а также другие константы и методы полезные при работе с примитивными типами данных.
В качестве типа также выступает любой созданный нами класс при создании инстанции класса. Вспомним прошлый урок, где мы создали класс Cat, а потом создали переменную ourcat типа Cat при создании экземпляра класса.
На этом закончим наше знакомство с переменными и типами в Java.
Итак, в этом уроке мы узнали какие бывают типы данных, научились объявлять переменные. В следующем уроке рассмотрим приведение типов.
Комментариев к записи: 15
Вопрос по типу String.
String myString = new String(«The weather was fine»);
Тут все понятно: создается объект myString класса(типа) String и методу-конструктору этого класса передается «The weather was fine» в качестве параметра.
Тогда что происходит здесь:
String myString = «The weather was fine»;
И в первом и во втором случае создается и инициализируется переменная типа String второй способ записи короче, и обычно используется он.
Спасибо за ответ (и за ответ по временам года — там все понятно), но тут хотелось бы уточнение. Как я понимаю String — это объектный тип, то есть попросту является классом со своим набором атрибутов и методов, а также имеет конструктор(насколько я правильно понял — это метод класса, имеющий имя своего класса и позволяющий задать параметры при создании объекта этого класса).
Я рассматриваю тип, как класс, а переменную, как объект.
Суть вопроса:
Если:
String myString = new String(«The weather was fine»);
тоже самое что:
String myString = «The weather was fine»;
тогда могу ли я также как во втором случае создавать объекты, например собственного класса, имеющего конструктор с параметрами?
Второй вариант это такая фишка, придуманная для типа String, что бы было проще им пользоваться, так как используется он очень часто, поэтому сделали так чтобы создавать переменную типа стринг было так же просто как и переменные примитивных типов. Но на самом деле String это объектный тип со всеми вытекающими, тут вы правы, поэтому как и для любого объектного типа для String имеется возможность создать объект при помощи ключевого слова new. Для своего собственного класса вы не сможете воспользоваться вторым вариантом при создании объекта.
Еще добавлю следующее пояснение из Java Tutorial
Во втором случае, то что заключено между кавычек является строковым литералом, каждый раз, когда такой литерал встречается в коде, компилятор создает объект типа String c этим значением.
Если с английским хорошо, то можете изучить эту сатью http://www.ntu.edu.sg/home/ehchua/programming/java/j3d_string.html Там подробно расписано про тип String особенно пункт 2.1 посмотрите
Теперь все понятно, спасибо большое 🙂
Во первых, спасибо Вам большое за отличный материал и доступную подачу!
Если я не ошибаюсь, у Вас небольшая ошибка в блоке:
» //объявление переменных типа byte.
byte getByte, putByte;
// инициализация переменных
byte getByte = 0;
byte putByte = 0;»
Во время инициализации переменных Вы указываете их тип, тем самым повторно объявляя их.
Спасибо за внимательность, исправила.
Cat ourcat=new cat();
1.А зачем присваивать переменной ourcat экземпляр класса Cat ?
2.допустим тип переменной int говорит о том что переменная этого типа будет целым числом, тип char о том что переменная будет символом ,а тип Cat о чем говорит? что переменная будет что ?
1. иначе она NULL будет
2. что переменная будет котом. тип Cat это указание того, что переменная может использовать методы из класса Cat и атрибуты у нее такие как описаны в классе Cat.
В предыдущем уроке перед вашим комментарием я отвечала Дмитрию и довольно подробно все расписала. Прочитайте, может поймете, если не поймете, то просто пока запомните эту конструкцию, может поймете в будущем на практике
Здравствуйте!
Программирую на С++ . Решил посмотреть на Java. И сразу же наткнулся на ваш сайт.
Я так понимаю Java — это упрощенный C++. Так вот = это перегруженный оператор присвоения,тоесть перегруженная функция.
из за того, что у Java подобный синтаксис — считать его упрощенным С++ неправильно
Как передать значение одной переменной другой, при условии что они разных типов? Например, от типа byte типу float?
преобразование переменных описано в уроке 7 http://study-java.ru/uroki-java/urok-7-preobrazovanie-tipov-v-java/ но конкретно перевода byte to float там нет, поэтому придеся гуглить
преобразование byte to float можно сделать с помощью кастинга например
float с;
byte а = (byte)c; вопрос в том а зачем оно вам нужно? Ведь при таком действии у float с будет отрезано все до размера byte и ваши значения просто будут неккоректными 🙂 но в джава все возможно !
Источник