What is reflection
Reflection is one of the characteristics of Java. It allows running Java programs to obtain their own information and can manipulate internal properties of classes or objects.
In layman's terms, through the reflection mechanism, you can obtain information about each type of member and member in a program or assembly at runtime.
Note that the point here is: runtime, not compile time. Under normal circumstances, the object types we write are determined during the compilation period. The Java reflection mechanism can dynamically create objects and call their properties, so that the way of creating objects is extremely flexible.
Although objects can be created dynamically through reflection, which increases flexibility, it is not available everywhere, and performance, encoding quantity, security, object-oriented, etc. must also be considered.
We know that Java is object-oriented. If the properties or methods in the object are operated through reflection mechanisms, the object-oriented characteristics will be destroyed to a certain extent. At the same time, private variables can be modified through the reflection mechanism, and there are certain security issues.
But this does not affect the application of reflection in practice. Almost all major frameworks are more or less using the Java reflection mechanism. Especially the mainstream Spring framework.
Functions and uses
Java reflection mainly provides the following functions:
At runtime, determine the class to which any object belongs;
Construct objects of any class at runtime;
At runtime, judge the member variables and methods of any class (the private method can even be called through reflection);
Calling methods of any object at runtime
One of the most important uses of reflection is to develop various general frameworks. Taking Spring as an example, when configuring a bean based on XML, we usually write the following code:
<bean class="">
</bean>
When Spring starts, it will use the reflection mechanism to load the corresponding UserServiceImpl class and then instantiate it. If this class does not exist, an exception will be thrown. Usually, the stack information of the invoke method call will also appear in the exception.
When Spring de-instances objects based on annotations, it also utilizes reflection mechanism. Here is a simple demo example to demonstrate how to obtain annotation information through reflection:
static void initUser(User user) throws IllegalAccessException {
// Get all attributes in the User class (getFields cannot obtain private attribute)
Field[] fields = ();// traverse all attributes
for (Field field : fields) {
// If this annotation is present on the attribute, perform the assignment operation
if (()) {
InitSex init = ();
(true);
// Set the gender value of the attribute
(user, ().toString());
("Complete the modification of the attribute value, the modification value is:" + ().toString());
}
}
}
We won't talk about more examples of Java reflection. It doesn’t matter if you don’t understand the above example now. Let’s introduce the specific use of the Java reflection mechanism in detail.
Simple example
Let’s learn about the Java reflection mechanism through a simple example comparison. First, let’s take a look at the example of creating and using objects under normal circumstances:
User user = new User();
("Official Account: New Horizons of Programs");
(3);
So, what should we do when we achieve a unified effect based on the reflection mechanism? See the following specific implementation:
@Test
public void testCreateReflect() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
InvocationTargetException, InstantiationException {
// Get the Class object corresponding to the User
Class clz = ("");
// Get the constructor without parameters in the User class
Constructor constructor = ();
// Create User object through the constructor
User user = (User) ();
("Official Account: New Program Vision");
(3);
("username=" + ());
("age=" + ());
}
In the above process, by obtaining the Class object corresponding to the User, obtaining the constructor Constructor, creating a User object through the constructor, and then calling the corresponding method.
Of course, the User class can also be completely eliminated in the following steps, and the corresponding Method can be obtained through the Class object and called. Examples are as follows:
Method setUsernameMethod = ("setUsername", );
Method setAgeMethod = ("setAge", );(obj,"public account: New Horizons of Programs");
(obj,3);
The same is true for the get method, so I won't repeat it.
After the above example, we have been able to create objects normally and use objects. Let’s take a look at the commonly used APIs for reflection. Through these APIs, we can implement more and more complex functions.
Commonly used reflection APIs
Three ways to get Class object
The first method: When you know the full path name of the class, you can use a static method to get the Class object. The above example is obtained by this method:
Class clz = ("");
The second method: obtain it through ".class". The prerequisite is that the corresponding class can be obtained before compilation.
Class clz = ;
The third type: use the getClass() method of the class object.
User user = new User();
Class clz = ();
Two ways to create an object
You can create an instance object of the class through the newInstance() method of the Class object and the newInstance() method of the Constructor object.
The first one: pass the newInstance() method of the Class object.
Class clz = ;
User user = (User) ();
The second type: pass the newInstance() method of the Constructor object.
Class clz = ("");
Constructor constructor = ();
User user = (User) ();
The second method can choose a specific constructor for creating a class object, while the Class object can only use the default parameterless constructor.
Class clz = ;
Constructor constructor = ();
User user = (User) ("Public Account: New Program Vision");
Get class attributes, methods, constructors
Get non-private properties through the getFields() method of the Class object.
Field[] fields = ();
for(Field field : fields){
(());
}
The User object attributes in the above example are all private and cannot be obtained directly through the above method. You can change one of the attributes to public and you can get them.
Get all properties through the getDeclaredFields() method of the Class object.
Field[] fields = ();
for(Field field : fields){
(());
}
Execute the print result:
username
age
Of course, other values for attributes can also be obtained. To modify private attributes, you need to call the (true) method first and then assign the value. Regarding the specific application, look back at the use of the annotation examples we first mentioned.
An example of obtaining the method is as follows:
Method[] methods = ();
for(Method method : methods){
(());
}
Print result:
setUsername
setAge
getUsername
getAge
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
It can be seen that not only the methods of the current class were obtained, but also the methods defined in the Object class of the parent class of the class were obtained.
The method of obtaining a constructor has been discussed above, so I will not repeat it again. The above methods have corresponding overloaded methods in Class and can be flexibly used according to the specific situation.
Create an array with reflection
Finally, let's look at another instance of creating an array through reflection.
@Test
public void createArray() throws ClassNotFoundException {
Class<?> cls = ("");
Object array = (cls,5);
// Add content to the array
(array,0,"Hello");
(array,1,"public account");
(array,2,"New Horizons of Programs");
(array,3,"Second Brother");
(array,4,"Java");
// Get the content of the specified position in the array
((array,2));
}
summary
I believe that after the above learning, I have a better understanding of the Java reflection mechanism. At the beginning, we have already mentioned that the reflection mechanism is also insufficient. Therefore, try to use orthodox writing as much as possible, but if you are developing a general framework, you can consider it.
The above is a detailed content of a comprehensive understanding of the Java reflection mechanism. For more information about the Java reflection mechanism, please pay attention to my other related articles!