Как получить имена параметров метода в Java 8 с использованием отражения?

Java 8 имеет возможность приобретать имена параметров метода с использованием Reflection API.

  1. Как я могу получить эти имена параметров метода?

  2. По моим сведениям, файлы classов не хранят формальные имена параметров. Как я могу получить их с помощью рефлексии?

4 Solutions collect form web for “Как получить имена параметров метода в Java 8 с использованием отражения?”

Как я могу получить эти имена параметров метода (некоторый пример кода)?

В принципе, вам необходимо:

  • получить ссылку на Class
  • Из Class получите ссылку на Method , вызвав Method getDeclaredMethod() или getDeclaredMethods() который возвращает ссылки на объекты Method
  • Из объекта Method вызов (новый по состоянию на Java 8) getParameters() который возвращает массив объектов Parameter
  • В объекте Parameter вызовите getName()
 Class clz = String.class; for (Method m : clz.getDeclaredMethods()) { System.err.println(m.getName()); for (Parameter p : m.getParameters()) { System.err.println(" " + p.getName()); } } 

Вывод:

 ... indexOf arg0 indexOf arg0 arg1 ... 

Также в соответствии с моими знаниями .class файлы не хранят формальный параметр. Тогда как я могу получить их с помощью отражения?

См. Javadoc для Parameter.getName() :

Если имя параметра присутствует , то этот метод возвращает имя, предоставленное файлом classа . В противном случае этот метод синтезирует имя формы argN , где N является индексом параметра в дескрипторе метода, который объявляет параметр.

Независимо от того, поддерживает ли JDK это, специфична для реализации (как вы можете видеть форму выше, assembly 125 JDK 8 ее не поддерживает). Формат файла classа поддерживает необязательные атрибуты, которые могут использоваться конкретной реализацией JVM / javac и которые игнорируются другими реализациями, которые его не поддерживают.

Обратите внимание, что вы даже можете генерировать вышеупомянутый вывод с помощью arg0 , arg1 , … с предварительными Java 8 JVM – все, что вам нужно знать, это количество параметров, которое доступно через Method.getParameterTypes() :

 Class clz = String.class; for (Method m : clz.getDeclaredMethods()) { System.err.println(m.getName()); int paramCount = m.getParameterTypes().length; for (int i = 0; i < paramCount; i++) { System.err.println(" arg" + i); } } 

Что нового в JDK 8 заключается в том, что существует расширенный API и возможность для JVMs предоставлять имена реальных параметров вместо arg0 , arg1 , ...

Поддержка таких дополнительных функций возможна с помощью дополнительных атрибутов, которые могут быть присоединены к различным структурам файлов classов. См. 4.6. Методы для структуры method_info в файле classа. См. Также 4.7.1. Определение и назначение новых атрибутов в спецификации JVM.

Поскольку с JDK 8 версия файла classа будет увеличена до 52, также можно будет изменить формат файла для поддержки этой функции.

См. Также JEP 118: Доступ к именам параметров во время выполнения для получения дополнительной информации и альтернатив реализации. Предложенная модель реализации заключается в добавлении необязательного атрибута, в котором хранятся имена параметров. Поскольку формат файла classов уже поддерживает эти необязательные атрибуты, это было бы даже возможно, чтобы файлы classов все еще могли использоваться более старыми JVM, где они просто игнорируются по требованию спецификации:

Реализации Java Virtual Machine необходимы для молча игнорирования атрибутов, которые они не распознают.

Обновить

Как было предложено @assylias, источник должен быть скомпилирован с помощью параметра командной строки javac -parameters , чтобы добавить метаданные для отражения имени параметра в файл classа. Однако это, конечно же, повлияет только на код, скомпилированный с этой опцией - вышеприведенный код будет по-прежнему печатать arg0 , arg1 и т. Д., Так как библиотеки времени выполнения не компилируются с этим флагом и, следовательно, не содержат необходимых записей в файлах classов.

Спасибо Андреасу, но, наконец, я получил полное решение из уроков Оракула по параметрам метода

В нем говорится,

Вы можете получить имена формальных параметров любого метода или конструктора с помощью метода java.lang.reflect.Executable.getParameters. (Класс Method и Constructor расширяет class Executable и, следовательно, наследует метод Executable.getParameters.) Однако файлы .class не сохраняют формальные имена параметров по умолчанию. Это связано с тем, что многие инструменты, которые производят и используют файлы classов, не могут ожидать большего статического и динамического следа .class-файлов, содержащих имена параметров. В частности, эти инструменты должны обрабатывать более крупные файлы .class, а виртуальная машина Java (JVM) будет использовать больше памяти. Кроме того, некоторые имена параметров, такие как секрет или пароль, могут предоставлять информацию о чувствительных к безопасности методах.

Чтобы хранить формальные имена параметров в определенном файле .class и, таким образом, позволить API Reflection извлекать формальные имена параметров, скомпилируйте исходный файл с параметром -parameters компилятору javac .

Как скомпилировать

Remember to compile the with the -parameters compiler option

Ожидаемый результат (Полный пример см. В ссылке, упомянутой выше)

java MethodParameterSpy ExampleMethods

Эта команда печатает следующее:

 Number of constructors: 1 Constructor #1 public ExampleMethods() Number of declared constructors: 1 Declared constructor #1 public ExampleMethods() Number of methods: 4 Method #1 public boolean ExampleMethods.simpleMethod(java.lang.String,int) Return type: boolean Generic return type: boolean Parameter class: class java.lang.String Parameter name: stringParam Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false Parameter class: int Parameter name: intParam Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false Method #2 public int ExampleMethods.varArgsMethod(java.lang.String...) Return type: int Generic return type: int Parameter class: class [Ljava.lang.String; Parameter name: manyStrings Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false Method #3 public boolean ExampleMethods.methodWithList(java.util.List) Return type: boolean Generic return type: boolean Parameter class: interface java.util.List Parameter name: listParam Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false Method #4 public  void ExampleMethods.genericMethod(T[],java.util.Collection) Return type: void Generic return type: void Parameter class: class [Ljava.lang.Object; Parameter name: a Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false Parameter class: interface java.util.Collection Parameter name: c Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false 

как хранится информация о параметрах метода (используется путем отражения) в intellij 13 , эквивалент «javac -параметров» в среде Eclipse IDE «Хранить информацию о параметрах метода (можно использовать с помощью отражения)» в окне -> Настройки -> Java – > Компилятор.

Вы можете использовать Paranamer lib ( https://github.com/paul-hammant/paranamer )

Пример кода, который работает для меня:

 import com.thoughtworks.paranamer.AnnotationParanamer; import com.thoughtworks.paranamer.BytecodeReadingParanamer; import com.thoughtworks.paranamer.CachingParanamer; import com.thoughtworks.paranamer.Paranamer; Paranamer info = new CachingParanamer(new AnnotationParanamer(new BytecodeReadingParanamer())); Method method = Foo.class.getMethod(...); String[] parameterNames = info.lookupParameterNames(method); 

Если вы используете Maven, поместите эту зависимость в свой pom.xml:

  com.thoughtworks.paranamer paranamer 2.8  
Interesting Posts

Насколько гибкими / сложными являются типы столбцов SQLite?

Понимание размеров сетки CUDA, размеров блоков и организации streamов (простое объяснение)

Подстановка клеток в формулу, которая содержит равные и котировки

rails 4: страницы пользовательских ошибок для 404, 500 и откуда отправляется сообщение об ошибке по умолчанию 500?

Как передавать анонимные типы в качестве параметров?

Преимущества авто в параметрах шаблона в C ++ 17

Как отключить tap-on-click (touchpad) на окнах

Слушатель событий на Java без приложения фокуса? (Глобальное обнаружение нажатия клавиш)

Как интерпретировать светодиодные и звуковые сигналы платы ASUS?

Java Singleton и синхронизация

Ссылка – проверка пароля

Создайте папку внутри папки документов в приложениях iOS

Ограничить доступ к определенному controllerу по IP-адресу в бета-версии ASP.NET MVC

Автозаполнение TextBox Control

Когда перегрузка проходит по ссылке (l-value и r-value), предпочтительной для передачи по значению?

Давайте будем гением компьютера.