What is Reflection

In the runtime state, for any class, you can know all the properties and methods of the class; for any object, you can call any of its methods and properties; this dynamically obtained information and dynamic invocation of the object’s methods is called the reflection mechanism of the Java language. So what can we do with reflection?

  • Analyze classes at runtime.
  • Look at objects at runtime. We can also use reflection to write a toString method for all classes to use.
  • Use the Method object to call any method of an object at runtime.

So this article will focus on the above three points to understand the reflection mechanism of Java. Before we start, let’s introduce a class that is essential for us to use in the process of reflection.

Class

At runtime, the Java runtime system maintains information for each object that identifies the type of the object, and the type that holds this information is the Class class. We can get the object’s Class object by using the object’s getClass() method, like the following.

1
2
User user = new User();
Class c = user.getClass();

Everything in this world has a meaning, so what can we do with Class objects? We most often use Class to determine if an object belongs to a certain type, like the following.

1
2
3
4
5
User user = new User();

if (user.getClass() == User.class) {
System.out.println("user is User");
}

Of course, we often use the getName() method of the Class class to get the name of a class. Sometimes we also use its newInstance() method to get an instance of a type (when it does not provide a common constructor).

Using reflection to analyze classes

Analyzing a class is just a matter of looking at the properties, methods and constructors of the class. The Java reflection package provides three classes Field, Method and Constructor to describe properties, methods and constructors respectively. Let’s take a look at how we can get this information about a class through the reflection mechanism.

  • Obtaining properties
1
2
3
4
User user = new User();
Class cl = user.getClass();
Field[] fields1 = cl.getFields();
Field[] fields2 = cl.getDeclaredFields();

You can see that we can use getFields() and getDeclaredFields() methods to get the list of properties in the class, so what is the difference between these two methods? The difference is that the former will only return information about the common members of the class, while the latter will return information about all the members of the class including public, private, and protected, but not the members of the parent class.

  • Get the constructor
1
2
Constructor[] constructors1 = cl.getConstructors();
Constructor[] constructors2 = cl.getDeclaredConstructors();
  • Get the methods
1
2
Method[] methods1 = cl.getMethods();
Method[] methods2 = cl.getDeclaredMethods();

You can see that we can easily get the properties, constructors and methods of a class through its Class object. But what api are provided in Field, Constructor and Method respectively? Let’s take a look at them together.

  1. getName() method, which is used to get the corresponding name. It exists in Field, Constructor and Method classes.
  2. getModifiers() method to get the previous modifiers (public, etc.), but getModifiers() returns an int value, which can be converted to a corresponding string by Modifier.toString(int i). Also present in both Field, Constructor and Method classes.
  3. getParameterTypes() method, used to get an array of parameter types for a method. Present in Constructor and Method classes
  4. getReturnType() method, used to get the return type of the method. Only exists in the Method class

With these api, we have the ability to analyze a class at runtime.

Using reflection to view objects

There are times when we may also need to reflect to get the value of the properties in the object, for example, when exporting Excel, we only know the field name of the property corresponding to the column, and then we need to reflect to get its value, and then write it to Excel. Then this section will look at how to use Java’s reflection mechanism to analyze the object together.

1
2
3
4
User user = new User(1, "itweknow");
Class cl = user.getClass();
Field userName = cl.getDeclaredField("userName");
Object value = userName.get(user);

As in the above code, we can use the get(Object obj) method provided in the Field class to get the value of the property, and specific get methods are provided for the base type, such as getDouble(). But if the above userName is a private property, the get() method will definitely throw an IllegalAccessException. This is where we need to use the setAccessible() method to override the security manager’s access control.

1
2
3
4
5
User user = new User(1, "itweknow");
Class cl = user.getClass();
Field userName = cl.getDeclaredField("userName");
userName.setAccessible(true);
Object value = userName.get(user);

The setAccessible() method is provided in the Field, Method, and Constructor classes. Echoing the get() method, Field also provides the set() method for setting values to properties.

Calling any method using reflection

The invoke() method is provided in the Method class to invoke the method wrapped in the current Method object. The definition of the invoke() method is as follows.

1
Object invoke(Object obj, Object... args)

The first argument is the object that invokes the method, and the second argument is the method’s parameters, which are in the form of an array. Let’s see how to use reflection to invoke the sayHello() method of the User class.

1
2
3
Method sayHelloMethod = cl.getDeclaredMethod("sayHello", String.class);
sayHelloMethod.setAccessible(true);
sayHelloMethod.invoke(user, "Reflect");

Look at the above code we get a private method named sayHello by getDeclaredMethod() method (PS: if it is a public method then just use getMethod() method), also for the private method we need to modify its access control to call it smoothly.

API collation

The above sections mentioned a lot of Api provided in the Java reflection mechanism, here are some common reflection Api that I have organized

  1. Class class
Api Description
forName() returns the Class object with the specified class name
newInstance() returns a new instance of the class
getFields() returns all the public properties of the class
getDeclaredField() returns all the properties of the class (public, private, protected)
getMethods() returns all the methods common to this class
getDeclaredMethods() returns all methods of this class (public, private, and protected)
getConstructors() returns all the public constructors of this class
getDeclaredConstructors() returns all constructors (public, private, protected) of this class
getField() & getDeclaredField() returns the property of this class with the specified name
getMethod() & getDeclaredMethod() returns the method with the specified name and parameters
cl.getConstructor() & cl.getDeclaredConstructor() get the constructor of the specified parameter
  1. Field class
Api Description
getModifiers() returns an integer value for the modifier used to describe the property. Use the toString() method of the Modifier class to convert it to a string.
getName() Returns a string used to describe the name of the property.
  1. Method class
Api Description
getModifiers() Returns an integer value used to describe the modifiers of the method. Use the toString() method of the Modifier class to convert it to a string.
getName() Returns a string used to describe the method name.
getParameterTypes() Returns an array of Class objects describing the types of the parameters.
getReturnType() Returns a Class object describing the return type.
invoke() invokes the method described by this object, passes the given parameters, and returns the return value of the method.
  1. Constructor class
Api Description
getModifiers() returns an integer value used to describe the constructor’s modifiers. Use the toString() method of the Modifier class to convert it to a string.
getName() Returns a string used to describe the name of the constructor.
getParameterTypes() Returns an array of Class objects to describe the parameter types.
  1. AccessibleObject class
Api Description
setAccessible(boolean flag) Sets the accessible flag for the reflected object. flag is true to block Java language access checking, so that the private properties of the object can also be queried and set.
isAccessible() Returns the value of the access flag for the reflection object.

Conclusion

This article is about the reflection mechanism of Java and the api provided by the Field, Method and Constructor classes under the reflection package.