Dynamic Access with Reflection

Basic Java
≈ 2 min read

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.

Do not make bypassing encapsulation an ordinary application technique. Dynamic access is justified in infrastructure code, libraries, and frameworks, but business code is usually simpler and more reliable when built on ordinary methods and types.