Dynamic Access with Reflection
When a member is selected at runtime
Reflection can do more than describe a type's structure. Field,
Method, and Constructor objects can be used for dynamic access.
This is useful, for example, in infrastructure code that receives a method name from configuration
or creates an instance of a class selected only when the application starts.
Invoking a method through Method
class Greeter {
public String greet(String name) {
return "Hello, " + name;
}
}
Greeter greeter = new Greeter();
Method method = Greeter.class.getMethod("greet", String.class);
Object result = method.invoke(greeter, "Ann");
The first argument to invoke() is the object on which an instance method is invoked,
while the remaining values are passed as the method's arguments. The return value has type Object
because reflection does not know the concrete result type at that call site in advance.
Creating an object through Constructor
Constructor<StringBuilder> constructor =
StringBuilder.class.getConstructor(int.class);
StringBuilder builder = constructor.newInstance(64);
Instead of a direct new, the constructor description is selected first,
and then newInstance() creates an object with the supplied arguments.
Reading and changing a field
class Counter {
public int value = 10;
}
Counter counter = new Counter();
Field field = Counter.class.getField("value");
int oldValue = (int) field.get(counter);
field.set(counter, 20);
A static field does not need a receiver object, while an instance field requires a concrete object. Reflection checks type compatibility at runtime, so many mistakes that the compiler would catch with direct access show up later here.
Non-public members and accessibility
For a non-public member, getDeclared... alone is not enough.
Reflection still respects access rules. trySetAccessible()
can attempt to enable access and return false if that is not possible.
In a modular application, module boundaries and opened packages also restrict such access.