36.1 Reflection Modern Usage
Use reflection judiciously in a modularized world with strong encapsulation and access controls.
Basic Reflection
import java.lang.reflect.*;
Class<?> clazz = MyClass.class;
Method m = clazz.getMethod("publicMethod", String.class);
Object result = m.invoke(instance, "arg");
Accessing Private Members
Field f = clazz.getDeclaredField("privateField");
f.setAccessible(true);
Object value = f.get(instance);
Module Encapsulation
With JPMS, private reflection requires explicit access:
// May throw InaccessibleObjectException
f.setAccessible(true);
Solution 1: --add-opens at Launch
java --add-opens com.example.module/com.example.internal=ALL-UNNAMED MyApp
Solution 2: opens in module-info
module com.example.module {
opens com.example.internal to com.framework;
}
Inspecting Annotations
if (clazz.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ann = clazz.getAnnotation(MyAnnotation.class);
String value = ann.value();
}
Performance
- Reflection is slower than direct calls.
- JVM optimizes repeated reflective calls but not as well as direct invocation.
- Prefer method handles for high-frequency calls.
Guidance
- Avoid reflection in hot code paths.
- Use
setAccessible(true)sparingly; prefer public APIs. - Document reflective access requirements (e.g., for frameworks).
- Consider method handles for better performance and type safety.