Explain Codes LogoExplain Codes Logo

Can I obtain method parameter name using Java reflection?

java
reflection-api
parameter-names
javac-compiler
Anton ShumikhinbyAnton Shumikhin·Jan 31, 2025
TLDR

To fetch method parameter names via Java reflection, ensure your class is compiled using the -parameters directive. The API java.lang.reflect.Parameter is then utilised to get the names:

import java.lang.reflect.Method; import java.lang.reflect.Parameter; // Get the method Method method = YourClass.class.getMethod("yourMethod", String.class); // Iterate and print each parameter name for (Parameter param : method.getParameters()) { System.out.println(param.getName()); }

Make sure to use -parameters when compiling, to yield actual parameter names. Otherwise, you'll encounter generic placeholders like arg0, arg1, etc.

Enforcing presence of parameter names during compilation

The bytecode of compiled Java classes does not house parameter names by default. To counter this and include parameter names, -parameters flag is passed to the Java compiler (javac).

Compile with JDK

javac -parameters YourClass.java

Maven compilation

Modify pom.xml to incorporate -parameters flag in maven-compiler-plugin configuration:

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin>

Working around with method parameters

Once you've enforced -parameters during compilation, method parameters can be obtained via the reflection API. Besides the name, the Parameter class can yield other metadata of interest.

Check for presence of parameter names

To avoid Java throwing curveballs at runtime, verify the presence of parameter names using isNamePresent():

Parameter[] params = method.getParameters(); for (Parameter param : params) { if (param.isNamePresent()) { // Party time! Parameter names are available. } else { // Uh-oh, fallback plan. } }

Iterate over class to fetch parameter metadata

If you need to fetch names and types for each method across an entire class:

for (Method method : YourClass.class.getDeclaredMethods()) { for (Parameter param : method.getParameters()) { // You know have name and type of every parameter! } }

Fall back strategies without -parameters

Can't apply -parameters? There's still hope! Consider using separate libraries or strategies to retrieve parameter names:

  • Paranamer library: Enabled to fetch parameter names provided bytecode houses debug information:

    // 'method' being an instance of java.lang.reflect.Method Paranamer paranamer = new CachingParanamer(); String[] parameterNames = paranamer.lookupParameterNames(method); // Paranamer to the rescue!
  • Spring Framework: Its built-in mechanics can retrieve parameter names:

    DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer(); String[] parameterNames = discoverer.getParameterNames(method); // Spring into action!

Working with Paranamer

While Paranamer is a handy tool, it requires bytecode to contain debug information. Ensure your code is compiled with debug information (-g flag). You can contribute to issues or the project's GitHub page.

Using descriptive fallback naming style

In scenarios where parameter names can't be retrieved and Paranamer is a no-go, consider using a descriptive naming style for parameters like intParam, stringParam, etc. This won't match the original names but offers some context to API consumers.

Reflect only on public methods

If you can't modify the compilation strategy for a library, focus on reflecting public methods. The Java API and most third-party libraries include parameter names for their public methods.