Reflection
Reflection Use Cases
Explore real-world applications of reflection in frameworks like Spring, JUnit, and Jackson.
Interview: Focuses on architectural trade-offs: when to use reflection vs. code generation, and the cost of runtime reflection.
While reflection should be avoided in basic business logic, it is essential for writing frameworks that must parse and execute arbitrary user code dynamically.
Core Idea
Reflection decouples frameworks from user code, enabling dynamic runtime configuration.
Why It Matters
Without reflection, developers would have to write repetitive configuration files to manage beans and serialize objects.
Interview Lens
Tests architectural decisions: evaluate when to use reflection vs. compile-time annotation processors.
Real-World Applications
- Dependency Injection (Spring): Resolves constructor parameters and autowires matching bean instances using reflection lookup.
- JSON Serialization (Jackson): Uses reflection to scan fields, match them to JSON keys, and instantiate classes dynamically during deserialization.
- Unit Testing (JUnit): Scans class structures for methods annotated with
@Testand executes them. - Dynamic Proxies: Java's
Proxyclass generates runtime implementations of interfaces, enabling Aspect-Oriented Programming (AOP) for transaction management.
Code Walkthrough
This program demonstrates how a basic test runner locates and runs test methods using reflection.
import java.lang.annotation.*; import java.lang.reflect.Method;@Retention(RetentionPolicy.RUNTIME) @interface MyTest {}
class SampleTest { @MyTest public void testOne() { System.out.println("Test one passed!"); } public void normalMethod() { System.out.println("Ignored."); } }
public class TestRunner { public static void main(String[] args) throws Exception { Class clazz = SampleTest.class; Object instance = clazz.getConstructor().newInstance();
for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(MyTest.class)) { method.invoke(instance); // Executes testOne() dynamically } } } }
Interview-Relevant Information
Q: How do modern frameworks (like Quarkus) differ from Spring regarding reflection?
Answer: Traditional frameworks use runtime reflection, which increases startup times and memory footprints. Modern cloud-native frameworks (like Quarkus or Micronaut) perform dependency injection and metadata processing at compile time using annotation processors. This eliminates runtime reflection overhead, enabling fast startup times suited for serverless scaling.
Quick Checklist
How does JUnit discover test methods? What is the alternative to runtime reflection? If yes, you understand reflection use cases.
Use Cases
Implementing Aspect-Oriented Logging or transaction wrappers around service beans.
Writing generic CSV or JSON data parsing engines.
Common Mistakes
Using runtime reflection inside hot loops, leading to performance bottlenecks.
Not catching classloading errors, causing crashes when plugins are missing.