Can I obtain method parameter name using Java reflection?

Viewed 155139

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?

15 Answers

To summarize:

  • getting parameter names is possible if debug information is included during compilation. See this answer for more details
  • otherwise getting parameter names is not possible
  • getting parameter type is possible, using 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.

The Paranamer library was created to solve this same problem.

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.

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.

You can't tell the name of the argument used.

You can retrieve the method signature with reflection and detect its argument types, however. Check getParameterTypes().

It is possible and Spring MVC 3 does it, but I didn't take the time to see exactly how.

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:

Taken from the spring documentation

While it is not possible (as others have illustrated), you could use 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).

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).

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 )

Overall in-short you can't get it unless you work on Source files directly (similar to what APT does at compile time).

One simple method to read additional symbol informations from Java bytecode is:

Reflector reflector = new Reflector();
JavaMethod method = reflector.reflect(Whatever.class)
    .getMethods()
    .stream()
    .filter(m -> "aMethod".equals(m.getName()))
    .findFirst()
    .get();
String paramName = method.getParameters().getVariables().get(0).getName();
System.out.println(paramName);

From Maven Central artifact:

<dependency>
    <groupId>com.intersult</groupId>
    <artifactId>coder</artifactId>
    <version>1.5</version>
</dependency>
Related