我可以使用 Java 反射获取方法参数名称吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2237803/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I obtain method parameter name using Java reflection?
提问by Geo
If I have a class like this:
如果我有这样的课程:
public class Whatever
{
public void aMethod(int aParam);
}
is there any way to know that aMethod
uses a parameter named aParam
, that is of type int
?
有没有办法知道aMethod
使用名为 的参数aParam
,即类型int
?
采纳答案by Bozho
To summarize:
总结一下:
- getting parameter names ispossible if debug information is included during compilation. See this answerfor more details
- otherwise getting parameter names is notpossible
- getting parameter type is possible, using
method.getParameterTypes()
- 如果在编译期间包含调试信息,则可以获取参数名称。有关更多详细信息,请参阅此答案
- 否则得到的参数名称是不是有可能
- 获取参数类型是可能的,使用
method.getParameterTypes()
For the sake of writing autocomplete functionality for an editor (as you stated in one of the comments) there are a few options:
为了为编辑器编写自动完成功能(如您在其中一条评论中所述),有几个选项:
- use
arg0
,arg1
,arg2
etc. - use
intParam
,stringParam
,objectTypeParam
, etc. - use a combination of the above - the former for non-primitive types, and the latter for primitive types.
- don't show argument names at all - just the types.
- 使用
arg0
,arg1
,arg2
等。 - 使用
intParam
,stringParam
,objectTypeParam
,等。 - 使用上述的组合 - 前者用于非原始类型,后者用于原始类型。
- 根本不显示参数名称 - 只显示类型。
回答by Johnco
You can retrieve the method with reflection and detect it's argument types. Check http://java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.html#getParameterTypes%28%29
您可以使用反射检索方法并检测它的参数类型。检查http://java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.html#getParameterTypes%28%29
However, you can't tell the name of the argument used.
但是,您无法说出所用参数的名称。
回答by danben
Parameter names are only useful to the compiler. When the compiler generates a class file, the parameter names are not included - a method's argument list only consists of the number and types of its arguments. So it would be impossible to retrieve the parameter name using reflection (as tagged in your question) - it doesn't exist anywhere.
参数名称仅对编译器有用。当编译器生成类文件时,不包括参数名称 - 方法的参数列表仅包含其参数的数量和类型。因此,不可能使用反射(如您的问题中所标记)来检索参数名称 - 它不存在于任何地方。
However, if the use of reflection is not a hard requirement, you can retrieve this information directly from the source code (assuming you have it).
但是,如果反射的使用不是硬性要求,您可以直接从源代码中检索此信息(假设您拥有它)。
回答by Elister
To add my 2 cents; parameter info is available in a class file "for debugging" when you use javac -g to compile the source. And it is available to APT but you'll need an annotation so no use to you. (Somebody discussed something similar 4-5 years ago here: http://forums.java.net/jive/thread.jspa?messageID=13467&tstart=0)
添加我的 2 美分;当您使用 javac -g 编译源代码时,参数信息在“用于调试”的类文件中可用。它对 APT 可用,但您需要一个注释,因此对您没有用。(有人在 4-5 年前在这里讨论过类似的事情:http: //forums.java.net/jive/thread.jspa?messageID=13467&tstart=0)
Overall in-short you can't get it unless you work on Source files directly (similar to what APT does at compile time).
总而言之,除非您直接处理源文件(类似于 APT 在编译时所做的),否则您无法获得它。
回答by flybywire
It is possible and Spring MVC 3 does it, but I didn't take the time to see exactly how.
这是可能的,Spring MVC 3 做到了,但我没有花时间去了解具体是如何做到的。
The matching of method parameter names to URI Template variable names can only be done if your code is compiled with debugging enabled. If you do have not debugging enabled, you must specify the name of the URI Template variable name in the @PathVariable annotation in order to bind the resolved value of the variable name to a method parameter. For example:
方法参数名称与 URI 模板变量名称的匹配只能在您的代码在启用调试的情况下编译时完成。如果未启用调试,则必须在@PathVariable 注释中指定 URI 模板变量名称的名称,以便将变量名称的解析值绑定到方法参数。例如:
Taken from the spring documentation
回答by Sarel Botha
The Paranamer library was created to solve this same problem.
Paranamer 库的创建是为了解决同样的问题。
It tries to determine method names in a few different ways. If the class was compiled with debugging it can extract the information by reading the bytecode of the class.
它尝试以几种不同的方式确定方法名称。如果类是通过调试编译的,它可以通过读取类的字节码来提取信息。
Another way is for it to inject a private static member into the bytecode of the class after it is compiled, but before it is placed in a jar. It then uses reflection to extract this information from the class at runtime.
另一种方法是在类编译之后,但在将其放入 jar 之前,将私有静态成员注入到类的字节码中。然后它使用反射在运行时从类中提取此信息。
https://github.com/paul-hammant/paranamer
https://github.com/paul-hammant/paranamer
I had problems using this library, but I did get it working in the end. I'm hoping to report the problems to the maintainer.
我在使用这个库时遇到了问题,但最终我确实让它工作了。我希望将问题报告给维护者。
回答by WhyNotHugo
While it is not possible (as others have illustrated), you coulduse an annotation to carry over the parameter name, and obtain that though reflection.
虽然这是不可能的(正如其他人所说明的那样),但您可以使用注释来携带参数名称,并通过反射获得该名称。
Not the cleanest solution, but it gets the job done. Some webservices actually do this to keep parameter names (ie: deploying WSs with glassfish).
不是最干净的解决方案,但它可以完成工作。一些网络服务实际上这样做是为了保留参数名称(即:使用 glassfish 部署 WS)。
回答by Markus Jevring
See java.beans.ConstructorProperties, it's an annotation designed for doing exactly this.
请参阅java.beans.ConstructorProperties,它是专为执行此操作而设计的注释。
回答by lpandzic
In Java 8 you can do the following:
在 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(){}
}
So for your class Whatever
we can do a manual test:
因此,对于您的课程,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;
}
}
}
}
which should print [aParam]
if you have passed -parameters
argument to your Java 8 compiler.
[aParam]
如果您已将-parameters
参数传递给 Java 8 编译器,则应该打印。
For Maven users:
对于 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>
For more information see following links:
有关更多信息,请参阅以下链接:
回答by Denis Danilkovich
see org.springframework.core.DefaultParameterNameDiscoverer class
参见 org.springframework.core.DefaultParameterNameDiscoverer 类
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
String[] params = discoverer.getParameterNames(MathUtils.class.getMethod("isPrime", Integer.class));