What is reflection?
If we have studied the underlying principles of the framework or written the framework ourselves, we must be familiar with the concept of reflection.
Reflection is called the soul of the framework mainly because it gives us the ability to analyze classes and execute methods in classes at run time.
Through reflection, you can get all the properties and methods of any class, and you can call these methods and properties.
Do you understand the application scenario of reflection?
For example, we usually write business code most of the time, and rarely come into contact with the scene of directly using reflection mechanism.
However, this does not mean that reflection is useless. On the contrary, it is because of reflection that you can use various frameworks so easily. Reflection mechanisms are widely used in frameworks such as Spring/Spring Boot and MyBatis.
Dynamic agents are also widely used in these frameworks, and the implementation of dynamic agents also depends on reflection.
For example, the following is the example code of implementing dynamic proxy through JDK, in which the reflection class Method is used to call the specified Method.
public class DebugInvocationHandler implements InvocationHandler { /** * Real objects in proxy classes */ private final Object target; public DebugInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException { System.out.println("before method " + method.getName()); Object result = method.invoke(target, args); System.out.println("after method " + method.getName()); return result; } }
In addition, like a sharp tool in Java, reflection is also used in the implementation of annotation.
Why does a @ Component annotation declare a class as Spring Bean when you use Spring? Why do you read the Value in the configuration file through an @ Value annotation? How does it work?
This is because you can analyze classes based on reflection and get annotations on class / property / method / method parameters. After you get the annotation, you can do further processing.
On the advantages and disadvantages of reflection mechanism
Advantages: it can make our code more flexible and provide out of the box functions for various frameworks
Disadvantages: it gives us the ability to analyze operation classes at run time, which also increases security problems. For example, you can ignore the security check of generic parameters (the security check of generic parameters occurs at compile time). In addition, the performance of reflection is also slightly worse, but it has little impact on the framework. Related reading: Java Reflection: Why is it so slow?
Reflection practice
Four ways to get Class objects
If we get this information dynamically, we need to rely on Class objects. The Class object tells the running program the methods, variables and other information of a Class. Java provides four ways to obtain Class objects:
1. If you know the specific category, you can use:
Class alunbarClass = TargetObject.class;
However, we generally do not know the specific Class. We basically obtain the Class object by traversing the Class under the package. The Class object obtained in this way will not be initialized
2. Get the path of the incoming class through Class.forName():
Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject");
3. Get through the object instance instance instance.getClass():
TargetObject o = new TargetObject(); Class alunbarClass2 = o.getClass();
4. Pass in the classpath through the classloader xxclassloader. Loadclass() to obtain:
Class clazz = ClassLoader.loadClass("cn.javaguide.TargetObject");
The Class object obtained through the Class loader will not be initialized, which means that some steps including initialization will not be carried out, and the static block and static object will not be executed
Some basic operations of reflection
1. Create a class TargetObject that we want to use reflection operation.
package cn.javaguide; public class TargetObject { private String value; public TargetObject() { value = "JavaGuide"; } public void publicMethod(String s) { System.out.println("I love " + s); } private void privateMethod() { System.out.println("value is " + value); } }
2. Use reflection to operate the methods and parameters of this class
package cn.javaguide; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Main { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException { /** * Gets the Class object of the TargetObject Class and creates an instance of the TargetObject Class */ Class<?> tagetClass = Class.forName("cn.javaguide.TargetObject"); TargetObject targetObject = (TargetObject) tagetClass.newInstance(); /** * Gets all defined methods in all classes */ Method[] methods = tagetClass.getDeclaredMethods(); for (Method method : methods) { System.out.println(method.getName()); } /** * Gets the specified method and calls */ Method publicMethod = tagetClass.getDeclaredMethod("publicMethod", String.class); publicMethod.invoke(targetObject, "JavaGuide"); /** * Gets the specified parameter and modifies it */ Field field = tagetClass.getDeclaredField("value"); //In order to modify the parameters in the class, we cancel the security check field.setAccessible(true); field.set(targetObject, "JavaGuide"); /** * Call the private method */ Method privateMethod = tagetClass.getDeclaredMethod("privateMethod"); //In order to call the private method, we cancel the security check privateMethod.setAccessible(true); privateMethod.invoke(targetObject); } }
Output content:
publicMethod privateMethod I love JavaGuide value is JavaGuide