Reflection API
java reflection API Class.forName getDeclaredMethod invoke setAccessible annotations Spring Hibernate runtime inspection
Introduction
In the previous lesson, you learned about Java Generics, which provide compile-time type safety and reusable code.
However, have you ever wondered how frameworks like Spring Boot, Hibernate, JUnit, Jackson, and Mockito work internally?
For example:
- How does Spring automatically create beans?
- How does Hibernate map Java objects to database tables?
- How does JUnit discover test methods?
- How does Jackson convert JSON into Java objects?
- How does Spring inject dependencies without explicitly creating objects?
The answer is Reflection.
The Java Reflection API allows a program to inspect and manipulate classes, methods, constructors, fields, and annotations at runtime.
Reflection is one of the most advanced Java topics and is extensively used in:
- Spring Framework
- Spring Boot
- Hibernate / JPA
- Jackson
- JUnit
- Mockito
- Dependency Injection
- ORM Frameworks
- REST Frameworks
- Annotation Processing
Understanding Reflection helps you understand how enterprise Java frameworks work behind the scenes.
In this lesson, you'll learn:
- What is Reflection?
- Why Reflection?
- Reflection Architecture
- Class Object
- Obtaining Class Objects
- Constructors
- Methods
- Fields
- Annotations
- Dynamic Object Creation
- Invoking Methods Dynamically
- Accessing Private Members
- Reflection Performance
- Security Considerations
- Best Practices
- Common Mistakes
- Hands-on Exercises
- Professional Interview Questions
What is Reflection?
Reflection is the ability of a Java program to inspect and manipulate its own structure at runtime.
Using Reflection, you can:
- Inspect classes
- Read fields
- Invoke methods
- Create objects
- Read annotations
- Discover constructors
- Access metadata
Example:
Running Program↓Reflection↓Inspect Class↓Invoke Methods↓Create Objects
Unlike normal Java code, Reflection works at runtime.
Why Reflection?
Normally:
Employee employee =new Employee();employee.display();
The compiler already knows:
- Class
- Method
- Constructor
With Reflection:
Class<?> clazz =Class.forName("Employee");
The class is discovered during execution.
Benefits:
- Dynamic Programming
- Framework Development
- Dependency Injection
- Object Mapping
- Testing
- Plugin Systems
Reflection Architecture
Class↓Constructors↓Methods↓Fields↓Annotations
The Class object is the entry point to Reflection.
What is Class<?> ?
Every Java class has an associated Class object.
Example:
String.class
Or:
Employee.class
The Class object stores metadata about the class.
Obtaining a Class Object
Method 1
Class<?> clazz =Employee.class;
Method 2
Employee employee =new Employee();Class<?> clazz =employee.getClass();
Method 3
Class<?> clazz =Class.forName("com.company.Employee");
Class.forName() loads a class dynamically by its fully qualified name.
Getting Class Information
Class<?> clazz =Employee.class;System.out.println(clazz.getName());System.out.println(clazz.getSimpleName());System.out.println(clazz.getPackageName());
Output:
com.company.EmployeeEmployeecom.company
Accessing Constructors
Constructor<?>[] constructors =Employee.class.getDeclaredConstructors();for(Constructor<?> constructor: constructors){System.out.println(constructor);}
Common methods:
- getConstructor()
- getDeclaredConstructor()
- getConstructors()
- getDeclaredConstructors()
Creating Objects Dynamically
Constructor<Employee> constructor =Employee.class.getConstructor();Employee employee =constructor.newInstance();
The object is created at runtime without using the new keyword directly.
Accessing Methods
Method[] methods =Employee.class.getDeclaredMethods();for(Method method : methods){System.out.println(method.getName());}
Invoking Methods
Method method =Employee.class.getMethod("display");Employee employee =new Employee();method.invoke(employee);
Output:
Employee Details
Passing Parameters
Method method =Employee.class.getMethod("setName",String.class);method.invoke(employee,"Rahul");
Reflection supports methods with parameters.
Accessing Fields
Field[] fields =Employee.class.getDeclaredFields();for(Field field : fields){System.out.println(field.getName());}
Reading Field Values
Field field =Employee.class.getDeclaredField("name");Employee employee =new Employee();field.setAccessible(true);field.set(employee,"Jagannath");System.out.println(field.get(employee));
Output:
Jagannath
Accessing Private Members
Normally:
private String password;
Reflection:
field.setAccessible(true);
Allows access to private fields and methods.
Note: Accessing private members using reflection may be restricted by the module system (Java 9+) or security policies.
Reading Annotations
Example:
@Entityclass Employee{}
Reflection:
boolean present =Employee.class.isAnnotationPresent(Entity.class);System.out.println(present);
Output:
true
Frameworks like Spring and Hibernate rely heavily on annotation processing.
Reflection with Custom Annotations
@Retention(RetentionPolicy.RUNTIME)@interface Author{String value();}
Usage:
@Author("Jagannath")class Course{}
Reading:
Author author =Course.class.getAnnotation(Author.class);System.out.println(author.value());
Reflection and Spring Boot
Spring scans classes:
Component@Service@Repository@Controller
Reflection:
- Finds annotations
- Creates objects
- Injects dependencies
- Calls constructors
Without Reflection, Spring's Dependency Injection would not be possible.
Reflection and Hibernate
Hibernate reads:
@Entity@Table@Id@Column
Reflection is used to:
- Read fields
- Create objects
- Populate entity values
- Generate SQL mappings
Reflection Performance
Normal Method Call:
employee.display();
Reflection:
method.invoke(employee);
Reflection is generally slower because:
- Metadata lookup
- Security checks
- Dynamic dispatch
- Runtime resolution
Therefore, avoid Reflection inside performance-critical loops.
Security Considerations
Reflection can:
- Access private members
- Modify internal state
- Bypass encapsulation
Use it responsibly and only when necessary.
Best Practices
Use Reflection Sparingly
Reflection adds flexibility but also complexity and runtime overhead.
Cache Reflection Metadata
Avoid repeatedly looking up methods or fields inside loops.
Prefer Public APIs
Use normal method calls whenever possible.
Handle Reflection Exceptions
Common exceptions include:
- ClassNotFoundException
- NoSuchMethodException
- NoSuchFieldException
- InvocationTargetException
- InstantiationException
- IllegalAccessException
Use Framework Support
In enterprise applications, let frameworks such as Spring and Hibernate manage Reflection whenever possible.
Common Mistakes
Using Reflection Unnecessarily
Direct method calls are simpler, safer, and faster.
Ignoring Checked Exceptions
Reflection APIs throw several checked exceptions that must be handled.
Forgetting setAccessible(true)
Private members cannot normally be accessed without overriding access checks (subject to module restrictions).
Repeated Metadata Lookup
Repeated calls to getDeclaredMethod() or getDeclaredField() can reduce performance.
Violating Encapsulation
Reflection should not be used to bypass class design unless there is a valid technical reason.
Hands-on Exercise
Create a Java program that:
- Loads a class using
Class.forName(). - Displays the class name and package.
- Lists all constructors.
- Lists all methods.
- Lists all fields.
- Dynamically creates an object using reflection.
- Invokes a method with parameters.
- Reads and updates a private field.
- Creates a custom annotation and reads it using Reflection.
- Measures the approximate execution time of a normal method call versus a reflective invocation.
Summary
The Java Reflection API enables runtime inspection and manipulation of classes, methods, fields, constructors, and annotations. Reflection is the foundation of many enterprise frameworks, including Spring Boot, Hibernate, JUnit, and Jackson. While Reflection provides exceptional flexibility, it should be used carefully because it introduces additional runtime overhead and can bypass normal encapsulation rules.
Key Takeaways
- Reflection inspects program metadata at runtime.
Class<?>is the entry point to the Reflection API.- Classes can be loaded dynamically using
Class.forName(). - Reflection can inspect constructors, methods, fields, and annotations.
- Objects can be created dynamically using constructors.
- Methods can be invoked dynamically.
- Private members can be accessed (subject to access restrictions).
- Enterprise frameworks rely heavily on Reflection.
- Reflection is slower than direct method invocation.
- Cache metadata and avoid unnecessary Reflection in performance-critical code.
Professional Interview Questions
1What is Reflection in Java?
Professional Answer
Reflection is a Java feature that allows a program to inspect and manipulate classes, constructors, methods, fields, and annotations at runtime. It enables dynamic object creation, method invocation, metadata inspection, and annotation processing. Reflection is widely used by enterprise frameworks such as Spring Boot, Hibernate, JUnit, and Jackson.
Follow-up Questions
- Which class is the entry point to Reflection?
- Why do frameworks use Reflection extensively?
Interview Tip: Remember: Reflection = Runtime Inspection + Runtime Manipulation.
2How can you obtain a Class object in Java?
Professional Answer
A Class object can be obtained in three common ways: 1. Using the .class literal (for example, Employee.class), 2. Calling getClass() on an object instance, 3. Loading a class dynamically using Class.forName("fully.qualified.ClassName"). Each approach ultimately provides access to the same metadata represented by the Class object.
Follow-up Questions
- Which method loads a class dynamically?
- When is Class.forName() commonly used?
Interview Tip: The three common approaches are: .class, getClass(), Class.forName().
3Why is Reflection slower than normal method calls?
Professional Answer
Reflection performs runtime metadata lookup, access checks, and dynamic method resolution before invoking members. Direct method calls are resolved more efficiently by the JVM and can benefit from optimizations such as inlining. Because of this additional overhead, Reflection should generally be reserved for framework development, dynamic programming, and infrastructure code rather than performance-critical business logic.
Follow-up Questions
- Should Reflection be used inside tight loops?
- How can Reflection performance be improved?
Interview Tip: Remember: Direct Call → Fast, Reflection → Flexible but Slower, Cache reflective metadata whenever possible.