Есть ли способ получить имена параметров метода в Java?

Я пишу небольшую и очень DRY framework, которая в значительной степени зависит от метаданных. Я хотел бы знать, есть ли способ получить имена параметров метода, т.е. С учетом некоторого метода

public void a(int myIntParam, String theString) { ... }

получить строки "myIntParam" и "theString".

Я знаю, что мог бы комментировать параметры, но это было бы неплохо...

public void a(
    @Param("myIntParam") int myIntParam,
    @Param("theString") String theString
) { ... }

Ответ 1

Мы создали пользовательскую аннотацию для метода, который содержит String [] имен параметров. Такой подход немного упростился, чем необходимость комментировать каждый отдельный параметр. Мы планируем добавить проверку времени сборки, чтобы количество имен аннотированных параметров совпало с количеством аргументов, так как это то, что нам нужно.

Ответ 2

Вот грязное решение, которое нуждается в некоторой настройке. Может быть, кто-то может сделать это лучше.

Минусы:

  • Требуется, чтобы вы знали местоположение скомпилированного файла класса.
  • Он должен быть скомпилирован с флагом -g.

Код:

import com.sun.org.apache.bcel.internal.classfile.ClassParser;
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.bcel.internal.classfile.LocalVariable;
import com.sun.org.apache.bcel.internal.classfile.Method;
import java.io.IOException;

public class Main {

  public static void main(String[] args) throws IOException {
      ClassParser parser = new ClassParser("Main.class");
      JavaClass clazz = parser.parse();

      for (Method m : clazz.getMethods()) {
          System.out.println("Method: " + m.getName());
          int size = m.getArgumentTypes().length;
          if (!m.isStatic()) {
            size++;
          }

          for (int i = 0; i < size; i++) {
              LocalVariable variable = m.getLocalVariableTable().getLocalVariable(i);
              System.out.println("  - Param: " + variable.getName());
          }
      }
  }

  public void a(int myIntParam, String theString) {
  }
}

Вывод:

$ javac -g Main.java
$ java Main
Method: <init>
- Param: this
Method: main
- Param: args
Method: a
- Param: this
- Param: myIntParam
- Param: theString

Ответ 3

Не совсем, но у кодовых книг есть эта библиотека, которая будет делать для многих целей: http://paranamer.codehaus.org/

Ответ 4

Я мог ошибаться в этом... но я не думаю, что имена параметров появляются в файле класса, поэтому я предполагаю, что нет способа получить их через отражение.

Ответ 5

Имя параметров присутствует в файле класса, когда код Java был скомпилирован с информацией об отладке (с помощью опции -g). Затем файл класса содержит атрибут LocalVariableTable (см. http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#5956). Здесь имена локальных переменных и параметров являются только локальными переменными. Параметры соответствуют слотам переменных, начинающимся с индекса 1 (или индексу 0 для статических методов).

Ответ 6

Если вы используете Spring, вам повезло. Просто добавьте это в свой applicationContext.xml:

<bean class="org.springframework.core.LocalVariableTableParameterNameDiscoverer"/>

Затем вы можете ввести этот bean, где это необходимо:

@Autowired
private ParameterNameDiscoverer parameterNameDiscoverer;

Method m = ...
String[] names = parameterNameDiscoverer.getParameterNames(m);

Как следует из названия, эта реализация основана на компиляции классов с информацией об отладке.

Ответ 7

@bobwienholt верен - имена параметров не скомпилированы в классы java и поэтому недоступны во время выполнения.

Ответ 8

Имена параметров доступны через apt (теперь часть javac).