Java Reflection — Inspecting and Manipulating Classes at Runtime
Fast recall
Quick revision
Core answer
Class> — obj.getClass(), Foo.class, or Class.forName("com.foo.Bar"). Use cases: framework internals (Spring DI wires beans by inspecting @Autowired fields; Jackson reads @JsonProperty; Hibernate maps @Entity fields to columns), testing (Mockito creates mock subclasses; JUnit finds @Test methods), serialization, annotation processing at runtime, and plugin systems (load classes by name). Costs: 10-100× slower than direct calls (though MethodHandle closes the gap), breaks encapsulation (setAccessible(true) bypasses private — restricted in Java 17+ by the module system), no compile-time type safety, and harder for the JIT to inline. Rule: use reflection only when necessary (frameworks, generic tooling), never in hot paths in application code.Whether you know what reflection does, can list real framework use cases, and understand its costs — especially encapsulation bypass and Java 17 module restrictions
Using reflection in application code instead of direct calls; forgetting that setAccessible(true) is restricted on JDK modules (Java 9+); not knowing MethodHandle is a faster alternative
Explain MethodHandle vs reflection performance, the Java 17 module access changes (`--add-opens`), and cite specific framework examples (Spring @Autowired, Jackson @JsonProperty)
Interview-ready guide
Interview answer
Reflection is Java's API for doing at runtime what's normally determined at compile time — looking up classes by name, reading and writing private fields, invoking methods, and discovering annotations. The entry point is java.lang.Class, and the core types are Field, Method, Constructor, and Annotation.
Why it matters: every serious Java framework uses reflection. Spring injects @Autowired fields by reflecting on bean classes. Jackson serializes POJOs by reading field annotations. Hibernate maps @Entity fields to database columns. Mockito creates mock subclasses. JUnit discovers @Test methods. Without reflection, every framework would require you to implement a special interface — the 'magic' of modern Java DI depends on reflection.
Costs: reflection is 10 to 100 times slower than direct calls — argument boxing, permission checks, indirect dispatch. For hot paths, cache the Method or Field object so you don't re-resolve per call. For truly performance-sensitive code, use MethodHandle from java.lang.invoke — it's much closer to direct-call speed and often JIT-inlined.
Encapsulation: reflection can bypass private with setAccessible(true). In Java 9 and the module system, this is restricted on JDK-internal types. In Java 17+, application modules also restrict reflective access unless they declare opens in module-info.java. The workaround is --add-opens on the command line — a common issue when upgrading legacy apps to modern Java.
When to use reflection in your own code: rarely. For framework code, generic tooling, or plugin systems — absolutely. For application code, prefer direct calls. If you find yourself reaching for reflection in a service, there's probably a design issue — an interface, generic type, or strategy pattern that would work better.
The modern alternative worth knowing: `MethodHandle` and the java.lang.invoke package — faster, more flexible, and the mechanism lambdas themselves use under the hood.
Java Reflection — Inspecting and Manipulating Classes at Runtime
Direct Answer
Reflection is Java's API for inspecting and manipulating classes, methods, fields, and constructors at runtime, even when their types aren't known at compile time. Access the entry point via Class<?> — obj.getClass(), Foo.class, or Class.forName("com.foo.Bar"). Use cases: framework internals (Spring DI wires beans by inspecting @Autowired fields; Jackson reads @JsonProperty; Hibernate maps @Entity fields to columns), testing (Mockito creates mock subclasses; JUnit finds @Test methods), serialization, annotation processing at runtime, and plugin systems (load classes by name). Costs: 10-100× slower than direct calls (though MethodHandle closes the gap), breaks encapsulation (setAccessible(true) bypasses private — restricted in Java 17+ by the module system), no compile-time type safety, and harder for the JIT to inline. Rule: use reflection only when necessary (frameworks, generic tooling), never in hot paths in application code.
Common Mistakes & Pitfalls
Using reflection in application code instead of direct calls; forgetting that setAccessible(true) is restricted on JDK modules (Java 9+); not knowing MethodHandle is a faster alternative
Check your understanding
Answer these without looking back at the article.
- How does `MethodHandle` differ from `Method.invoke` in performance?
- What does `setAccessible(true)` do, and why is it restricted in Java 17+?
- How does Spring use reflection to inject `@Autowired` fields?
- Why is reflection a bad choice for a tight hot loop in application code?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.