0% found this document useful (0 votes)
0 views36 pages

Reflection API Java

The document discusses the Java Reflection API, which allows for dynamic inspection and manipulation of classes, methods, and fields at runtime. It outlines the advantages and disadvantages of using reflection, including its use in frameworks, serialization, and testing, while also highlighting performance overhead and security risks. A code example demonstrates various reflection capabilities, such as retrieving constructors, methods, fields, superclasses, interfaces, and annotations of a class.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views36 pages

Reflection API Java

The document discusses the Java Reflection API, which allows for dynamic inspection and manipulation of classes, methods, and fields at runtime. It outlines the advantages and disadvantages of using reflection, including its use in frameworks, serialization, and testing, while also highlighting performance overhead and security risks. A code example demonstrates various reflection capabilities, such as retrieving constructors, methods, fields, superclasses, interfaces, and annotations of a class.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

Relfection in java and use of

Reflection in PatchMapping
In the world of Java programming, one powerful tool that often remains in
the shadows is the Java Reflection API. Reflection allows us to inspect and
manipulate classes, fields, methods, and constructors during runtime. It
provides a way to work with Java classes dynamically, making it a versatile
tool for tasks like introspection, testing, debugging, and even creating
flexible frameworks.

In this tutorial, we’ll dive into the Java Reflection API using a
comprehensive code example. We’ll explore the various aspects of
reflection, including class inspection, method invocation, field access, and
more, using a simple Employee class.

What is Java Reflection?


Java Reflection is a feature that allows us to examine or modify the runtime
behavior of applications. It provides access to class metadata, allowing us
to inspect and manipulate classes, methods, fields, and other class
members.

Pros of Java Reflection:


1. Dynamic Code Inspection: Reflection allows us to examine and analyze
classes, methods, fields, and other class members dynamically at
runtime. This can be extremely useful in scenarios where we need to
work with unknown classes or dynamically loaded classes.
2. Extensibility and Flexibility: Reflection can make our code more
extensible and flexible. It enables us to create plugins, extensions, and
frameworks that can work with classes and objects in a generic way,
without having to know the exact class structure at compile time.
3. Debugging and Profiling: Reflection can be valuable for debugging and
profiling tools. We can use it to inspect and monitor the state of objects
and classes during runtime, aiding in debugging complex applications.
4. Code Generation: Some code generation and serialization frameworks
use reflection to inspect classes and generate code or data structures
dynamically, saving developers from writing repetitive code.
5. Annotations and Metadata: Reflection is often used to process
annotations and metadata associated with classes and methods. This is
prevalent in frameworks like Spring and Hibernate, where annotations
are used to configure and control behavior.

Cons of Java Reflection:


1. Performance Overhead: One of the significant drawbacks of reflection
is its performance overhead. Reflective operations can be significantly
slower than equivalent non-reflective operations. This is because
reflective access involves dynamic method lookup and field access,
which is slower than direct access.
2. Type Safety: Reflection bypasses some of the type-checking
mechanisms provided by the Java compiler. This can lead to runtime
exceptions, such as ClassCastException, if we don't use reflection
carefully.
3. Complexity and Maintainability: A code that heavily relies on reflection
can be hard to understand and maintain. It might not be clear from the
code itself what classes and methods are being used, making it
challenging to follow the logic and debug issues.
4. Security Risks: Reflection can potentially introduce security risks,
especially when used in untrusted environments. Malicious code might
use reflection to access or modify private fields and methods of
classes.
5. Limited Tool Support: Some development tools, like static code
analyzers and refactoring tools, may not work correctly with code that
uses reflection extensively. This can impact the overall development
experience.

When to Use Java Reflection:


Java Reflection is a powerful tool, but it should be used judiciously. Here
are some scenarios where it can be appropriate:

Frameworks and Libraries: Reflection is often used in frameworks and


libraries that need to work with diverse classes and objects provided by
users or third parties.
Serialization and Deserialization: Many serialization frameworks, like
JSON or XML parsers, use reflection to map between data and class
structures.
Dependency Injection: Dependency injection containers, like Spring,
often use reflection to instantiate and inject dependencies into classes.
Testing and Debugging Tools: Reflection can be valuable for creating
testing and debugging tools that need to inspect and manipulate
objects during runtime.
Dynamic Configuration: In cases where we need to configure an
application dynamically based on external configuration files or user
preferences, reflection can be helpful.

Getting Started
To get started with Java Reflection, we’ll need a basic understanding of
classes and objects in Java. We’ll use a simple Person & Employee class and
Permanent interface in our example.
package models;

public interface Permanent {


public abstract void getBonus();
}

package models;

/**
* Person
*/
public class Person {
private String firstName;
private String lastName;
private int age;

public Person() {
}

public Person(String firstName, String lastName, int age) {


this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// Getter methods
public String getFirstName() {
return firstName;
}

public String getLastName() {


return lastName;
}

public int getAge() {


return age;
}

// Setter methods
public void setFirstName(String firstName) {
this.firstName = firstName;
}

public void setLastName(String lastName) {


this.lastName = lastName;
}

public void setAge(int age) {


this.age = age;
}

@Override
public String toString() {
return "Person{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", age=" + age +
'}';
}

package models;

/**
* Employee
*/
public class Employee extends Person implements Permanent{
private String company;
public Employee() {
}

public Employee(String company) {


this.company = company;
}

// Getter method
public String getCompany() {
return company;
}

// Setter method
public void setCompany(String company) {
this.company = company;
}

@Override
public String toString() {
return "Employee{" +
"company='" + company + '\'' +
'}';
}

private void sayHi(String message){


System.out.println(message);
}

@Override
public void getBonus() {
System.out.println("Method 'getBonus'");
}
}

1. Getting Constructors
// Getting constructors of the class
Class<?> extractClass = Class.forName("models.Employee");
System.out.println("\n\n\n------------- Class Constructors -------------");
Constructor<?>[] constructors = extractClass.getConstructors();
System.out.println("Constructors : "+ Arrays.toString(constructors));

In the provided code snippet, we are using Java Reflection to obtain


information about the constructors of a class represented by the
extractClass object. Here's a brief explanation of what this code does:
1. Constructor<?>[] constructors = extractClass.getConstructors();: This
line retrieves an array of Constructor objects from the extractClass
class. These Constructor objects represent the constructors that can be
used to create instances of the class.
2. System.out.println("Constructors : "+Arrays.toString(constructors));:
Here, we are printing the obtained constructors to the console.
Arrays.toString(constructors) converts the array of constructors into a
human-readable string format and then concatenates it with the
"Constructors:" label before printing it to the console.

In summary, this code snippet uses Java Reflection to list and display the
constructors available for the extractClass class. Constructors are special
methods used to create new instances of a class, and this code provides
information about them at runtime.

2. Getting Methods
// Getting methods of the class
Class<?> extractClass = Class.forName("models.Employee");
System.out.println("\n\n\n------------- Class Methods -------------");
Method[] classMethods = extractClass.getDeclaredMethods();
System.out.println("Class Methods : "+ Arrays.toString(classMethods));

// Getting methods of the class and super class methods


System.out.println("\n\n\n------------- All Methods -------------");
Method[] allMethods = extractClass.getMethods();
System.out.println("All Methods : "+ Arrays.toString(allMethods));

This code snippet uses Java Reflection to obtain information about the
methods of a class, both those declared within the class and those
inherited from superclasses. Let’s break down each part of the code:

1. Method[] classMethods = extractClass.getDeclaredMethods();:


extractClass is an instance of the Class class, representing a specific
class (e.g., the "Employee" class). getDeclaredMethods() is a method
provided by the Class class. It returns an array of Method objects
representing only the methods that are declared within the class itself.
These Method objects contain details such as the method names,
return types, parameters, and modifiers. The code assigns this array of
declared methods to the classMethods variable.
2. System.out.println("Class Methods : "+ Arrays.toString(classMethods));:
Here, the code prints the obtained Method objects to the console.
Arrays.toString(classMethods) converts the array of Method objects
into a human-readable string format. This allows us to see the names of
the methods declared within the class. The result is displayed along
with the label “Class Methods:” to indicate that the output represents
information about the methods declared within the class.
3. Method[] allMethods = extractClass.getMethods();: This line retrieves an
array of Method objects using the getMethods() method. Unlike
getDeclaredMethods(), this method returns methods not only declared
within the class but also methods inherited from its superclasses. These
Method objects represent all accessible methods in the class hierarchy.
4. System.out.println("All Methods : "+ Arrays.toString(allMethods));: This
code prints the obtained Method objects from both the class and its
superclasses to the console. Arrays.toString(allMethods) converts the
array of Method objects into a human-readable string format. The result
is displayed along with the label “All Methods:” to indicate that the
output represents information about all accessible methods in the class
hierarchy.

3. Getting Fields
// Getting fields of the class
Class<?> extractClass = Class.forName("models.Employee");
System.out.println("\n\n\n------------- Class Fields -------------");
Field[] classFields = extractClass.getDeclaredFields();
System.out.println("Class Fields : "+ Arrays.toString(classFields));

// Getting fields of the class and super class fields


System.out.println("\n\n\n------------- All Fields -------------");
Field[] allFields = extractClass.getFields();
System.out.println("All Fields : "+ Arrays.toString(allFields));

This code snippet uses Java Reflection to obtain information about the
fields (variables) of a class, both those declared within the class and those
inherited from superclasses. Let’s break down each part of the code:

1. Field[] classFields = extractClass.getDeclaredFields();: extractClass is an


instance of the Class class, representing a specific class (e.g., the
"Employee" class). getDeclaredFields() is a method provided by the
Class class. It returns an array of Field objects representing only the
fields that are declared within the class itself. These Field objects
contain details such as the field names, types, and modifiers. The code
assigns this array of declared fields to the classFields variable.
2. System.out.println("Class Fields : "+ Arrays.toString(classFields));: Here,
the code prints the obtained Field objects to the console.
Arrays.toString(classFields) converts the array of Field objects into a
human-readable string format. This allows us to see the names and
types of the fields declared within the class. The result is displayed
along with the label “Class Fields:” to indicate that the output
represents information about the fields declared within the class.
3. Field[] allFields = extractClass.getFields();: This line retrieves an array of
Field objects using the getFields() method. Unlike getDeclaredFields(),
this method returns fields not only declared within the class but also
fields inherited from its superclasses. These Field objects represent all
accessible fields in the class hierarchy.
4. System.out.println("\n\n\n------------- All Fields -------------");: Similar to
the previous separator line, this line prints another separator line to
visually separate the output for the “All Fields” section.
5. System.out.println("All Fields : "+ Arrays.toString(allFields));: This code
prints the obtained Field objects from both the class and its
superclasses to the console. Arrays.toString(allFields) converts the
array of Field objects into a human-readable string format. The result is
displayed along with the label “All Fields:” to indicate that the output
represents information about all accessible fields in the class hierarchy.

4. Getting Super Class


// Getting super class using reflection
Class<?> extractClass = Class.forName("models.Employee");
System.out.println("\n\n\n------------- Super Class Name -------------");
System.out.println("Super Class Name: "+ extractClass.getSuperclass());

This code snippet uses Java Reflection to retrieve information about the
superclass of a class represented by the extractClass variable. Let's break
down what each part of the code is doing:

1. System.out.println("Super Class Name: "+


extractClass.getSuperclass());: Here, the code prints the name of the
superclass of the class represented by the extractClass variable.
extractClass.getSuperclass() is a method provided by the Class class. It
returns the Class object representing the immediate superclass of the
class. The result is displayed along with the label “Super Class Name:”
to indicate that the output represents the name of the superclass.

5. Getting Interfaces
// Getting interfaces using reflection
Class<?> extractClass = Class.forName("models.Employee");
System.out.println("\n\n\n------------- Interfaces -------------");
System.out.println("Interfaces: "+ Arrays.toString(extractClass.getInterfaces()));

This code snippet uses Java Reflection to retrieve information about the
interfaces implemented by a class represented by the extractClass
variable. Let's break down what each part of the code is doing:

1. System.out.println("Interfaces: "+
Arrays.toString(extractClass.getInterfaces()));: Here, the code prints the
names of the interfaces implemented by the class represented by the
extractClass variable. extractClass.getInterfaces() is a method provided
by the Class class. It returns an array of Class objects, each
representing an interface that the class implements. Arrays.toString() is
used to convert the array of interface names into a string for printing.
The result is displayed along with the label “Interfaces:” to indicate that
the output represents the interfaces implemented by the class.

6. Getting a Class Modifier


// Getting class modifier using reflection
Class<?> extractClass = Class.forName("models.Employee");
System.out.println("\n\n\n------------- Class modifier -------------");
System.out.println("Class Modifier: "+ Modifier.toString(extractClass.getModifiers()));

This code snippet uses Java Reflection to retrieve and print information
about the modifiers applied to a class represented by the extractClass
variable. Let's break down what each part of the code is doing:

1. System.out.println("Class Modifier: "+


Modifier.toString(extractClass.getModifiers()));: Here, the code prints
the modifiers applied to the class represented by the extractClass
variable. extractClass.getModifiers() is a method provided by the Class
class. It returns an integer representing a bitmask of modifiers (e.g.,
public, private, abstract) applied to the class. Modifier.toString() is used
to convert the integer bitmask into a human-readable string
representation of the modifiers. The result is displayed along with the
label “Class Modifier:” to indicate that the output represents the
modifiers of the class.

7. Getting Annotations
// Getting annotations of the class and super class fields
System.out.println("\n\n\n------------- All Anotation -------------");
Class<?> extractClass = Class.forName("models.Employee");
Annotation[] allAnnotations = extractClass.getAnnotations();
System.out.println("All Fields : "+ Arrays.toString(allAnnotations));

This code snippet utilizes Java Reflection to retrieve and print all
annotations applied to a class, including any annotations inherited from
superclasses. Let’s break down what each part of the code is doing:

1. Class<?> extractClass = Class.forName("models.Employee");: Here, the


code obtains a reference to the Class object representing the
"models.Employee" class. This is achieved using Class.forName(), which
loads and returns the Class object for the specified class name.
2. Annotation[] allAnnotations = extractClass.getAnnotations();: The code
retrieves all annotations applied to the extractClass (Employee) using
the getAnnotations() method. This method returns an array of
java.lang.annotation.Annotation objects representing the annotations
present in the class.
3. System.out.println("All Fields : "+ Arrays.toString(allAnnotations));:
Finally, the code prints the array of annotations used Arrays.toString()
to convert the array into a human-readable string. This output displays
all the annotations applied to the class.

8. Invoke Private Methods


// Invoking private method (sayHi) of the class from another class using reflection
System.out.println("\n\n\n------------- Invoking private method (sayHi) of the class from another class using
reflection -------------");
Employee employee = new Employee("ABC Inc.");

Class<?> employeeClass = employee.getClass();


Method sayHiMethod = employeeClass.getDeclaredMethod("sayHi", String.class);
sayHiMethod.setAccessible(true);

sayHiMethod.invoke(employee, "Hello from Reflection!");

sayHiMethod.setAccessible(false);

code snippet demonstrates how to use Java Reflection to invoke a private


method, sayHiof the Employee class from another class. Here's a
breakdown of what each part of the code does:

1. Employee employee = new Employee("ABC Inc.");: Here, an instance of


the Employee class is created and initialized with the company name
"ABC Inc."
2. Class<?> employeeClass = employee.getClass();: The code obtains the
Class object representing the runtime class of the employee object
using the getClass() method.
3. Method sayHiMethod = employeeClass.getDeclaredMethod("sayHi",
String.class);: The getDeclaredMethod method is used to retrieve a
reference to the private method named "sayHi" from the Employee
class. The method's name and its parameter types are specified as
arguments.
4. sayHiMethod.setAccessible(true);: Before invoking the private method,
it is necessary to make it accessible by calling setAccessible(true) on
the sayHiMethod object. This is because private methods are not
typically accessible from outside the class, but Reflection allows us to
bypass this restriction.
5. sayHiMethod.invoke(employee, "Hello from Reflection!");: The invoke
method is used to execute the sayHi method on the employee object. It
takes two arguments: the first argument is the object on which the
method should be invoked (employee in this case), and the second
argument is the argument to be passed to the sayHi method.
6. sayHiMethod.setAccessible(false);: After invoking the private method,
it’s good practice to set the method’s accessibility back to its original
state for security reasons. In this case, it is set to false restore the
private method's private status.

9. Access Private Fields


// Access private fields from another class in java using Reflection Api
System.out.println("\n\n\n------------- Access private fields from another class in java using Reflection Api ---------
----");

Employee employee1 = new Employee("ABC Inc.");

Class<?> employeeClass1 = employee.getClass();


Field companyField = employeeClass1.getDeclaredField("company");

companyField.setAccessible(true);

String companyValue = (String) companyField.get(employee);


System.out.println("Company: " + companyValue);

companyField.set(employee, "XYZ Corp.");


System.out.println("Updated Company: " + employee.getCompany());

companyField.setAccessible(false);

This code snippet demonstrates how to access and modify a private field
(company) of the Employee class from another class using Java Reflection.
Let's break down each part of the code:

1. Employee employee1 = new Employee("ABC Inc.");: Here, an instance of


the Employee class is created and initialized with the company name
"ABC Inc.".
2. Class<?> employeeClass1 = employee.getClass();: The code obtains the
Class object representing the runtime class of the employee object
using the getClass() method. Note that there is a mistake here, and it
should be Employee.class instead of employee.getClass().
3. Field companyField = employeeClass1.getDeclaredField("company");:
This line is used getDeclaredField to obtain a reference to the private
field named "company" of the Employee class.
4. companyField.setAccessible(true);: Before accessing or modifying the
private field, it is necessary to make it accessible by calling
setAccessible(true) on the companyField object. This step is required
because private fields are not normally accessible from outside the
class.
5. String companyValue = (String) companyField.get(employee);: Using the
get method on the companyField, the code retrieves the value of the
private field "company" from the employee object. The result is cast to
a String.
6. System.out.println("Company: " + companyValue);: The retrieved value
of the “company” field is printed to the console, showing the initial
value of the company.
7. companyField.set(employee, "XYZ Corp.");: After making the private
field accessible, the code uses the set method on companyField to
modify the value of the "company" field in the employee object. It sets
the company name to "XYZ Corp."
8. System.out.println("Updated Company: " + employee.getCompany());:
Finally, the updated value of the “company” field is printed to the
console by calling the getCompany method of the employee object.
9. companyField.setAccessible(false);: After accessing and modifying the
private field, it is a good practice to reset the accessibility to false
maintain security and encapsulation. This line sets the companyField
back to non-accessible.

10. Create Class Instances


// Creating class instance using Reflection Api
System.out.println("\n\n\n------------- Creating class instance using reflection Reflection Api -------------");

Class<?> employeeClass3 = Class.forName("models.Employee");

Constructor<?> employeeConstructor = employeeClass3.getDeclaredConstructor();

Object employeeInstance = employeeConstructor.newInstance();

Employee employee3 = (Employee) employeeInstance;

employee3.setCompany("IT Conquest");
employee3.getCompany();
System.out.println(employee3.getCompany());

This code snippet demonstrates how to create an instance of a class


(Employee) using Java Reflection. Let's break down each part of the code:

1. Class<?> employeeClass3 = Class.forName("models.Employee");: Here, a


Class object (employeeClass3) is obtained using Class.forName() by
providing the fully qualified class name, which is "models.Employee".
This step is essential to dynamically load the class definition.
2. Constructor<?> employeeConstructor =
employeeClass3.getDeclaredConstructor();: The code obtains a
reference to the default constructor of the Employee class using the
getDeclaredConstructor() method. Since the Employee class has a
default constructor with no arguments, this step retrieves that
constructor.
3. Object employeeInstance = employeeConstructor.newInstance();: Using
the employeeConstructor, an instance of the Employee class is created
dynamically by invoking the constructor's newInstance() method. The
result is stored in the employeeInstance variable, which is of type
Object. At this point, We have a new instance of the Employee class.
4. Employee employee3 = (Employee) employeeInstance;: To work with the
newly created instance as an Employee object, the code casts
employeeInstance to the Employee class, creating a strongly typed
reference named employee3.
5. employee3.setCompany("IT Conquest");: The code uses the
setCompany method of the employee3 object to set the company name
to "IT Conquest".
6. employee3.getCompany();: The getCompany method is called on the
employee3 object to retrieve the company name. However, the
returned value is not used or printed in this code snippet.
7. System.out.println(employee3.getCompany());: Finally, the company
name stored in the employee3 object is printed to the console using
System.out.println().

11. Generating Methods

To generate methods dynamically in the Employee class using Java


Reflection, We can follow these steps:

1. Load the Employee class using Class.forName() or by obtaining its Class


object.
2. Use the Class.getDeclaredMethod() method to obtain a Method object
representing the method we want to generate. If the method doesn't
exist, we can create one.
3. Define the method’s signature, including its name, return type, and
parameter types.
4. Use the Class.getDeclaredMethod() method to check if the method
already exists. If it does, we can modify it; otherwise, we can create a
new method.
5. If we need to create a new method, we can use libraries like ASM or
Javassist to dynamically generate bytecode for the method.

Here’s a simplified example of generating a new method in the Employee


class using Java Reflection:
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.Arrays;

public class EmployeeMethodGenerator {


public static void main(String[] args) throws Exception {
// Load the Employee class
Class<?> employeeClass = Class.forName("models.Employee");

// Define the method's signature


String methodName = "newMethod";
Class<?> returnType = void.class;
Class<?>[] parameterTypes = { String.class };

// Check if the method already exists


Method existingMethod = null;
try {
existingMethod = employeeClass.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException ignored) {
// The method doesn't exist; we can create it
}

if (existingMethod != null) {
System.out.println("Method already exists: " + existingMethod);
} else {
// Create a new method
Method newMethod = createNewMethod(employeeClass, methodName, returnType, parameterTypes);

// Add the new method to the class


employeeClass.getDeclaredMethods(); // Trigger class initialization
System.out.println("New method created: " + newMethod);
}
}

private static Method createNewMethod(Class<?> declaringClass, String methodName, Class<?> returnType,


Class<?>[] parameterTypes) throws Exception {
// Use libraries like ASM or Javassist to generate bytecode for the new method.
// This example only demonstrates method creation but doesn't generate bytecode.

// Define the new method


Method newMethod = new Method(methodName, returnType, parameterTypes, Modifier.PUBLIC);

// Print method signature


System.out.println("Creating a new method: " + newMethod);

// we would typically use bytecode generation libraries to add the method to the class.
// For simplicity, this example does not include bytecode generation.
// Instead, it prints the method signature.

return newMethod;
}
}

In this example, we check if the method with a specific name and


parameter types already exists in the Employee class. If it doesn't exist, we
create a new Method an object that represents the method with the
specified signature. Note that the actual bytecode generation to add the
method to the class is not included in this example, as it requires additional
libraries like ASM or Javassist. This example serves as a basic outline of
how we might approach dynamic method generation using Java Reflection.

Conclusion:
Java Reflection is a valuable tool for scenarios where dynamic behavior
and introspection are required. It empowers frameworks, libraries, and
tools to work with a wide range of classes and objects. However, it should
be used judiciously due to its potential performance and security
implications. When considering its usage, developers should carefully
weigh the benefits against the disadvantages and ensure that it aligns with
the specific requirements of the application or system. In many cases,
alternatives such as using interfaces, abstract classes, or design patterns
may provide a more maintainable and efficient solution.
Java Reflection
In Java, reflection allows us to inspect and manipulate classes, interfaces,
constructors, methods, and fields at run time.

There is a class in Java named Class that keeps all the information about objects
and classes at runtime. The object of Class can be used to perform reflection.

Reflection of Java Classes


In order to reflect a Java class, we first need to create an object of Class.

And, using the object we can call various methods to get information about
methods, fields, and constructors present in a class.

There exists three ways to create objects of Class:

1. Using forName() method

Here, the forName() method takes the name of the class to be reflected as its
argument.

2. Using getClass() method

Here, we are using the object of the Dog class to create an object of Class.
3. Using .class extension

Now that we know how we can create objects of the Class. We can use this object
to get information about the corresponding class at runtime.

Example: Java Class Reflection


Output

In the above example, we have created a superclass: Animal and a subclass: Dog.
Here, we are trying to inspect the class Dog.

Notice the statement,

Here, we are creating an object obj of Class using the getClass() method. Using the
object, we are calling different methods of Class.
obj.getName() - returns the name of the class
obj.getModifiers() - returns the access modifier of the class
obj.getSuperclass() - returns the super class of the class

To learn more about Class, visit Java Class (official Java documentation).

Note: We are using the Modifier class to convert the integer access modifier to a
string.

Reflecting Fields, Methods, and Constructors


The package java.lang.reflect provides classes that can be used for manipulating
class members. For example,

Method class - provides information about methods in a class


Field class - provides information about fields in a class
Constructor class - provides information about constructors in a class

1. Reflection of Java Methods


The Method class provides various methods that can be used to get information
about the methods present in a class. For example,
Output

In the above example, we are trying to get information about the methods present
in the Dog class. As mentioned earlier, we have first created an object obj of Class
using the getClass() method.

Notice the expression,


Here, the getDeclaredMethod() returns all the methods present inside the class.

Also, we have created an object m of the Method class. Here,

m.getName() - returns the name of a method


m.getModifiers() - returns the access modifier of methods in integer form
m.getReturnType() - returns the return type of methods

The Method class also provides various other methods that can be used to inspect
methods at run time. To learn more, visit the Java Method class (official Java
documentation).

2. Reflection of Java Fields


Like methods, we can also inspect and modify different fields of a class using the
methods of the Field class. For example,
Output

In the above example, we have created a class named Dog. It includes a public field
named type. Notice the statement,

Here, we are accessing the public field of the Dog class and assigning it to the
object field1 of the Field class.

We then used various methods of the Field class:

field1.set() - sets the value of the field


field1.get() - returns the value of field
field1.getModifiers() - returns the value of the field in integer form
Similarly, we can also access and modify private fields as well. However, the
reflection of private field is little bit different than the public field. For example,
Output

In the above example, we have created a class named Dog. The class contains a
private field named color. Notice the statement.

Here, we are accessing color and assigning it to the object field1 of the Field class.
We then used field1 to modify the accessibility of color and allows us to make
changes to it.

We then used field1 to perform various operations on the private field color.
To learn more about the different methods of Field, visit Java Field Class (official
Java documentation).

3. Reflection of Java Constructor


We can also inspect different constructors of a class using various methods
provided by the Constructor class. For example,
Output
In the above example, we have created a class named Dog. The class includes two
constructors.

We are using reflection to find the information about the constructors of the class.
Notice the statement,

Here, the we are accessing all the constructors present in Dog and assigning them
to an array constructors of the Constructor type.

We then used object c to get different informations about the constructor.

c.getName() - returns the name of the constructor


c.getModifiers() - returns the access modifiers of the constructor in integer
form
c.getParameterCount() - returns the number of parameters present in each
constructor

what is the use of reflection in


PatchMapping

🔍 Reflection in PATCH (and general dynamic updates):


In the context of implementing PATCH in Spring Boot, Reflection can be used when:

You don’t want to hardcode switch-case for every field.


You want to dynamically access and update fields in an object at runtime based on keys
received from the client (e.g., in Map<String, Object>).

✅ Example Use of Reflection in PATCH


Let’s say you receive this PATCH payload:

And you want to update those fields on the User entity without writing switch-cases for each
one.

🔧 Code Example: Reflection-based Field Update


🧠 How Reflection Helps Here:
Without Reflection With Reflection

You write logic for each field One generic loop handles all

Tedious for large entities Scales well with large classes

Cannot handle unknown fields Can handle dynamically at runtime

⚠️ Drawbacks / Caution When Using Reflection


1. Bypasses compile-time safety — runtime errors if fields are misspelled or types don't
match.
2. Performance — slower than direct field access, but usually acceptable unless in large
loops.
3. Security — may accidentally expose or allow updates to fields like id, password, etc.

🛡️ Best Practice with Reflection


Before using reflection to set a field:

Use a field whitelist to allow only specific fields to be updated.


Add type checks before setting.
Ignore sensitive or auto-managed fields like id, createdAt, password.

✅ Optional: Whitelist Approach


✅ Summary
🔍 Feature ✔ Reflection Benefit
Dynamically update fields ✅
Fewer lines of code ✅
Works for large entities ✅
Needs careful security validation ⚠️
Harder to debug/type-safe ⚠️

write a reusable utility class that uses reflection to


apply a PATCH update safely to any entity?
Awesome! Here's a reusable utility class in Java that uses Reflection to apply PATCH updates
to any entity class safely. This class:
✅ Supports dynamic field updates
✅ Ignores null values
✅ Allows optional whitelisting
✅ Avoids sensitive fields like id, password, etc.
✅ 1. PatchUtil Utility Class

✅ 2. How to Use in Your UserService


✅ 3. Example PATCH Request

🧠 Why This Is Useful:


Works for any entity (User, Product, Article, etc.)
Centralized logic – no need to rewrite patch logic in every service
Secure: you can control which fields are patchable

✅ Optional Improvements:
You can extend PatchUtil to:

Log before/after values for audit trail


Automatically validate field types (e.g., int, boolean)
Add support for nested objects (like address.city)

You might also like