Reflection API Java
Reflection API Java
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.
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;
package models;
/**
* Person
*/
public class Person {
private String firstName;
private String lastName;
private int age;
public Person() {
}
// Setter methods
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@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() {
}
// 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 + '\'' +
'}';
}
@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 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));
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:
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));
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:
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:
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.
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:
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:
sayHiMethod.setAccessible(false);
companyField.setAccessible(true);
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:
employee3.setCompany("IT Conquest");
employee3.getCompany();
System.out.println(employee3.getCompany());
if (existingMethod != null) {
System.out.println("Method already exists: " + existingMethod);
} else {
// Create a new method
Method newMethod = createNewMethod(employeeClass, methodName, returnType, parameterTypes);
// 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;
}
}
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.
And, using the object we can call various methods to get information about
methods, fields, and constructors present in a class.
Here, the forName() method takes the name of the class to be reflected as its
argument.
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.
In the above example, we have created a superclass: Animal and a subclass: Dog.
Here, we are trying to inspect the class Dog.
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.
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.
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).
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.
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).
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.
And you want to update those fields on the User entity without writing switch-cases for each
one.
You write logic for each field One generic loop handles all
✅ Optional Improvements:
You can extend PatchUtil to: