---
title: Reflection in Java - Scaler Topics
description: This article by Scaler Topics covers What is Reflection in Java with applications, examples, and explanations; read to know more.
category: Java
author: Priyansh Goyal
---
:::section{.main}
Reflection in Java is a unique feature in the Java programming language that provides us with a way to get information regarding the class to which an object belongs and the methods of that class that can be executed using that object.
We can use Java Reflection to invoke these methods at runtime without knowing their names and change their behaviour at runtime.
[IMAGE {1} {CREATE A SIMILAR GRAPHIC} START SAMPLE]
https://media.geeksforgeeks.org/wp-content/uploads/20220110121120/javalang.jpg
[IMAGE {1} FINISH SAMPLE]
### Uses of Reflection
Reflection in Java is a powerful feature with various use cases:
* It allows classes to be loaded dynamically at runtime, enabling applications to load classes that are not known at compile time.
* It is commonly used in debugging and testing frameworks to inspect and manipulate objects during runtime, facilitating the creation of generic test cases and debugging tools.
* Frameworks like Spring use reflection extensively for configuration and dependency injection, allowing developers to define beans and wire dependencies without explicit configuration.
* It plays a crucial role in serialization and deserialization mechanisms, where objects are converted to and from byte streams. Libraries like Jackson and Gson utilize reflection to map Java objects to JSON and vice versa.
While reflection provides flexibility and power, it should be used judiciously due to its performance overhead and potential security risks.
### How to Invoke a Method through Reflection?
#### Method 1: getDeclaredMethod()
`getDeclaredMethod()` is a method the Java Reflection API provides. It allows you to obtain a Method object representing a method of a class, including non-public methods.
#### Method 2: invoke()
The `invoke()` method, part of Java's Reflection API, executes a method dynamically. It's called on a Method object obtained through reflection, taking the target object instance (or null for static methods) and method arguments as parameters.
```java
package org.scaler.note;
public class Employee {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public double calculateSalary(double bonus) {
return this.salary + bonus;
}
}
```
```java
import java.lang.reflect.Method;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// Get the class object for Employee
Class<?> employeeClass = Class.forName("org.scaler.note.Employee");
// Get the method object for calculateSalary with parameter type double
Method calculateSalaryMethod = employeeClass.getDeclaredMethod("calculateSalary", double.class);
// Create an instance of Employee
Object employeeInstance = employeeClass.getConstructor(String.class, double.class).newInstance("John", 50000.0);
// Invoke the calculateSalary method with a bonus of 2000
double bonus = 2000;
double totalSalary = (double) calculateSalaryMethod.invoke(employeeInstance, bonus);
System.out.println("Total Salary: " + totalSalary);
}
}
```
**Output:**
```plaintext
Total Salary: 52000.0
```
**Explanation:** In this example, after creating an instance of Employee, we directly obtain the Method object for calculateSalary using getDeclaredMethod(). Then, we set its accessibility to true (if it's private) and invoke it using the invoke() method, passing the instance of Employee and the bonus parameter. Finally, we print the total salary returned using this method.
#### Method 3: Class.getDeclaredField(FieldName)
The `getDeclaredField()` method retrieves a Field object representing a declared field of the class. It allows access to non-public fields and accepts the field name as its parameter. This facilitates dynamic access to class fields during runtime via reflection in Java.
#### Method 4: Field.setAccessible(true)
The setAccessible(accurate) method, employed on a Field object obtained through reflection, enables access to non-public fields. It overrides access restrictions, allowing modification or retrieval of field values that would otherwise be inaccessible due to encapsulation.
```java
package org.scaler.note;
public class Employee {
private double salary;
public Employee(double salary) {
this.salary = salary;
}
// Getter and setter for salary (not shown for brevity)
}
```
```java
import java.lang.reflect.Field;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// Get the class object for Employee
Class<?> employeeClass = Class.forName("org.scaler.note.Employee");
// Create an instance of Employee
Object employeeInstance = employeeClass.getConstructor(double.class).newInstance(50000.0);
// Get the field object for the private field 'salary'
Field salaryField = employeeClass.getDeclaredField("salary");
// Make the field accessible (since it's private)
salaryField.setAccessible(true);
// Get the current value of the salary field
double currentSalary = (double) salaryField.get(employeeInstance);
System.out.println("Current Salary: " + currentSalary);
// Modify the value of the salary field
salaryField.set(employeeInstance, 55000.0);
// Get the updated value of the salary field
double updatedSalary = (double) salaryField.get(employeeInstance);
System.out.println("Updated Salary: " + updatedSalary);
}
}
```
**Output:**
```plaintext
Current Salary: 50000.0
Updated Salary: 55000.0
```
**Explanation:** In this example, we first obtain the Class object for Employee. Then, we create an instance of Employee using reflection. Next, we use getDeclaredField() to obtain a reference to the private salary field. After making the field accessible, we can get its current value using get() and modify it using set(). Finally, we print the salary field's current and updated values.
:::
:::section{.main}
## Important Points on Reflection API in Java
1. The Reflection API in Java allows for dynamic inspection and manipulation of classes, interfaces, fields, and methods at runtime.
2. It provides a way to dynamically analyze and modify the structure and behaviour of Java applications.
3. Reflection can be used for tasks such as introspecting classes, accessing private members, invoking methods dynamically, and creating instances of classes dynamically.
4. While powerful, reflection should be used judiciously due to its potential performance overhead and complexity.
5. It enables frameworks like Spring and Hibernate to perform tasks like dependency injection and object-relational mapping without requiring explicit configuration.
6. Reflection can be beneficial in scenarios where the structure of classes is not known at compile time, such as in generic programming or plugin systems.
7. Java's Reflection API is integral to many advanced Java libraries and frameworks, facilitating tasks such as serialization, testing, and debugging.
8. Security concerns arise with reflection, as it can be used to access sensitive information or modify critical components of a Java application.
9. Despite its power, developers should strive to minimize the use of reflection in performance-critical code and favour more straightforward, statically-typed alternatives where possible.
10. Proper understanding and usage of the Reflection API can significantly enhance the flexibility and capabilities of Java applications, but it should be employed thoughtfully and with caution.
### Example
```java
import java.lang.annotation.*;
import java.lang.reflect.*;
class Person {
private int id;
private String name;
private int age;
public Person(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args) {
Class<?> c = Person.class;
// Constructor array
Constructor<?>[] constructors = c.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("Name of Constructor : " + constructor);
System.out.println("Count of constructor parameters : " + constructor.getParameterCount());
Parameter[] parameters = constructor.getParameters();
for (Parameter parameter : parameters) {
System.out.println("Constructor's parameter : " + parameter);
}
System.out.println();
}
System.out.println();
// Method Array
Method[] methods = c.getDeclaredMethods();
System.out.println("Length of methods : " + methods.length);
for (Method method : methods) {
System.out.println("Method name: \t" + method);
System.out.println("Method return type : \t" + method.getReturnType());
System.out.println("Method parameter count: \t" + method.getParameterCount());
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
System.out.println("Method's Parameter : " + parameter);
}
System.out.println();
}
System.out.println();
// Annotations
Class<?>[] classes = c.getDeclaredClasses();
for (Class<?> class1 : classes) {
System.out.println("class: " + class1);
System.out.println("Name of class: " + class1.getName());
}
System.out.println();
// Annotations
Annotation[] anno = c.getDeclaredAnnotations();
for (Annotation annotation : anno) {
System.out.println("Annotation: " + annotation);
}
}
}
```
**Output:**
```plaintext
Name of Constructor : public Person(int,java.lang.String,int)
Count of constructor parameters : 3
Constructor's parameter : int arg0
Constructor's parameter : java.lang.String arg1
Constructor's parameter : int arg2
Length of methods : 8
Method name: public void Person.setId(int)
Method return type : void
Method parameter count: 1
Method's Parameter : int arg0
Method name: public int Person.getAge()
Method return type : int
Method parameter count: 0
Method name: public void Person.setAge(int)
Method return type : void
Method parameter count: 1
Method's Parameter : int arg0
Method name: public static void Person.main(java.lang.String[])
Method return type : void
Method parameter count: 1
Method's Parameter : java.lang.String[] arg0
Method name: public java.lang.String Person.toString()
Method return type : class java.lang.String
Method parameter count: 0
Method name: public java.lang.String Person.getName()
Method return type : class java.lang.String
Method parameter count: 0
Method name: public void Person.setName(java.lang.String)
Method return type : void
Method parameter count: 1
Method's Parameter : java.lang.String arg0
Method name: public int Person.getId()
Method return type : int
Method parameter count: 0
```
:::
::: section{.main}
## Advantages and Disadvantages of Reflection in Java
**Advantages:**
1. It enables dynamic runtime inspection of classes, interfaces, methods, and fields.
2. It allows the invocation of methods, instantiation of classes, and modification of field values dynamically.
3. It facilitates the development of Visual Development Environments and class browsers, aiding developers in writing correct code.
**Disadvantages:**
1. It violates encapsulation principles by allowing access to private methods and fields, potentially leaking sensitive data.
2. It introduces performance overhead as types are resolved dynamically, preventing JVM optimization and resulting in slower operations.
:::
:::section{.summary}
## Conclusion
* **Reflection in Java** is a way through which we can gather information about classes and their methods and alter or modify their behaviour at runtime.
* It provides dynamic access to class metadata, enabling tasks like instantiation, method invocation, and field manipulation.
* It supports frameworks and libraries that require runtime analysis and manipulation of classes and objects.
* It increased flexibility in implementing advanced debugging, logging, and testing functionalities.
* However, Reflection should be used judiciously due to potential performance overhead, security concerns, and increased code complexity.
:::