Explain Codes LogoExplain Codes Logo

Java Reflection: How to get the name of a variable?

java
reflection
debugging
performance
Alex KataevbyAlex Kataev·Feb 26, 2025
TLDR

Though local variable names are inaccessible at runtime, class field names can be plucked out using Reflection. Here's how that can be accomplished:

import java.lang.reflect.Field; public class Sample { private String myField; public static void main(String[] args) throws Exception { Sample obj = new Sample(); Field field = obj.getClass().getDeclaredField("myField"); // Let there be light... and behold 'myField' System.out.println(field.getName()); } }

Beware: Only names of fields that have not been obfuscated during the compilation will appear. Those of the local variables are unavailable as they vanish post-compile.

Understanding the '-g' compiler option

When you have to deal with local variables, make use of -g option with javac:

javac -g MyClass.java

The -g option is the magic trick that keeps local variable names intact in the bytecode. However, don't rely on standard reflection APIs to get access to the local variable names even with this -g option. For a more robust solution, consider bytecode libraries like ASM for parsing this information during runtime.

Java 8's -parameters compiler option

With Java 8, accessing parameter names became less convoluted, thanks to the -parameters option:

javac -parameters MyClass.java

With -parameters, you can work with getParameters() on a Method object and retrieve the parameter names via reflection. Do note that this isn't applicable to other local variables within method bodies.

Inspecting class files using javap

Use javap command—a handy decipherer—to read variable names in class files:

javap -l -c MyClass

The -l option displays the LocalVariableTable, a list containing names and types of local variables. However, this information can be absent if class files were compiled without debug information.

JPDA: The advanced debugger

For elaborate debugging scenarios, consider the Java Platform Debugger Architecture (JPDA). It allows you fine-grained control over variables during execution, including tricky local variables. Though it may sound daunting, it's just the thing you need for high-complexity debugging tasks.

Considerations when using reflection

Remember that using reflection to manipulate fields can lead to shared references and potential problems down the line. Reflection often carries a performance toll, hence use it judiciously. Weigh the added value versus the overhead you're introducing into your codebase.

Reflection: A necessary evil?

Finally, if you're finding yourself needing to access local variable names often, you may want to take a step back and evaluate your architecture. It might be the right moment to carry out some much-needed refactoring to better align with what Java allows you to do naturally.