Reflection

Reflection is the JVM's ability to inspect and modify classes, methods, and fields at runtime — regardless of what was known at compile time. The java.lang.reflect package powers frameworks like Spring (dependency injection), Jackson (JSON binding), JUnit (test discovery) and Hibernate (ORM mapping).

Basic reflection

Class<?> cls = Class.forName("com.example.User");
Object instance = cls.getDeclaredConstructor().newInstance();

Method m = cls.getMethod("setName", String.class);
m.invoke(instance, "Ada");

Field f = cls.getDeclaredField("email");
f.setAccessible(true);  // bypass private
f.set(instance, "ada@example.com");

Inspecting a class

Class<?> cls = User.class;
for (Method m : cls.getDeclaredMethods()) {
    System.out.println(m.getName() + " returns " + m.getReturnType());
}
for (Field f : cls.getDeclaredFields()) {
    System.out.println(f.getType() + " " + f.getName());
}

Cost and caveats

  • Slower than direct calls — JIT can't optimise reflective invocations as aggressively.
  • Bypasses type safety — errors show up at runtime, not compile time.
  • Bypasses encapsulation with setAccessible(true) — controversial, and restricted by the Java Platform Module System for internal JDK classes.

Modern alternatives

For many use cases, MethodHandle (Java 7+) and VarHandle (Java 9+) provide reflection-like capabilities with better performance. For JSON binding, annotation processors and compile-time code generation (Records + pattern matching) are increasingly common.