我可以使用Java反射获取方法参数名吗?

Geo*_*Geo 116 java reflection

如果我有这样的课程:

public class Whatever
{
  public void aMethod(int aParam);
}
Run Code Online (Sandbox Code Playgroud)

有没有办法知道,aMethod使用一个名为参数aParam,即类型的int

lpa*_*zic 93

在Java 8中,您可以执行以下操作:

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;

public final class Methods {

    public static List<String> getParameterNames(Method method) {
        Parameter[] parameters = method.getParameters();
        List<String> parameterNames = new ArrayList<>();

        for (Parameter parameter : parameters) {
            if(!parameter.isNamePresent()) {
                throw new IllegalArgumentException("Parameter names are not present!");
            }

            String parameterName = parameter.getName();
            parameterNames.add(parameterName);
        }

        return parameterNames;
    }

    private Methods(){}
}
Run Code Online (Sandbox Code Playgroud)

因此,对于您的课程,Whatever我们可以进行手动测试:

import java.lang.reflect.Method;

public class ManualTest {
    public static void main(String[] args) {
        Method[] declaredMethods = Whatever.class.getDeclaredMethods();

        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.getName().equals("aMethod")) {
                System.out.println(Methods.getParameterNames(declaredMethod));
                break;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

[aParam]如果已将-parameters参数传递给Java 8编译器,则应该打印.

对于Maven用户:

<properties>
    <!-- PLUGIN VERSIONS -->
    <maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>

    <!-- OTHER PROPERTIES -->
    <java.version>1.8</java.version>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven-compiler-plugin.version}</version>
            <configuration>
                <!-- Original answer -->
                <compilerArgument>-parameters</compilerArgument>
                <!-- Or, if you use the plugin version >= 3.6.2 -->
                <parameters>true</parameters>
                <testCompilerArgument>-parameters</testCompilerArgument>
                <source>${java.version}</source>
                <target>${java.version}</target>
            </configuration>
        </plugin>
    </plugins>
</build>
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅以下链接

  1. 官方Java教程:获取方法参数的名称
  2. JEP 118:在运行时访问参数名称
  3. 参数类的Javadoc

  • 我不知道他们是否更改了编译器插件的参数,但是使用最新版本(现在为3.5.1)我必须在配置部分使用编译器参数:<configuration> <compilerArgs> <arg> - 参数</ arg> </ compilerArgs> </ configuration> (2认同)

Boz*_*zho 84

总结一下:

  • 如果在编译期间包含调试信息,可以获取参数名称.有关详细信息,请参阅此答案
  • 否则得到的参数名称是不是有可能
  • 使用获取参数类型是可能的 method.getParameterTypes()

为了编写编辑器的自动完成功能(正如您在其中一条评论中所述),有几个选项:

  • 使用arg0,arg1,arg2等.
  • 使用intParam,stringParam,objectTypeParam,等.
  • 使用上述的组合 - 前者用于非基本类型,后者用于基本类型.
  • 根本不显示参数名称 - 只是类型.

  • Interfaces可以实现吗?我仍然找不到获取接口参数名称的方法. (4认同)

Sar*_*tha 15

创建Paranamer库是为了解决同样的问题.

它尝试以几种不同的方式确定方法名称.如果使用调试编译类,则可以通过读取类的字节码来提取信息.

另一种方法是在编译之后,在将它放入jar之前,将私有静态成员注入到类的字节码中.然后,它使用反射在运行时从类中提取此信息.

https://github.com/paul-hammant/paranamer

我在使用这个库时遇到了问题,但最终确实让它工作了.我希望向维护者报告这些问题.


Kar*_*ról 9

是.
代码必须使用符合Java 8的编译器进行编译,并带有用于存储正式参数名称的选项(-parameters选项).
然后,此代码段应该有效:

Class<String> clz = String.class;
for (Method m : clz.getDeclaredMethods()) {
   System.err.println(m.getName());
   for (Parameter p : m.getParameters()) {
    System.err.println("  " + p.getName());
   }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

请参阅org.springframework.core.DefaultParameterNameDiscoverer类

DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
String[] params = discoverer.getParameterNames(MathUtils.class.getMethod("isPrime", Integer.class));
Run Code Online (Sandbox Code Playgroud)


Joh*_*nco 5

您可以使用反射检索方法并检测它的参数类型.查看http://java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.html#getParameterTypes%28%29

但是,您无法分辨所使用的参数的名称.

  • 真的,这一切都是可能的.然而,他的问题是明确地**关于**参数名称**.检查topictitle. (16认同)
  • 这个问题没有以他不知道获得这种类型的方式制定. (3认同)