Reflection mechanism of Java Foundation

Posted by Paavero on Mon, 14 Feb 2022 16:30:28 +0100

preface

Recently, when learning AOP of Spring framework, I want to know about dynamic proxy first. Other blogs say that the idea of dynamic proxy is related to Java reflection mechanism. Based on the principle of finding other blogs to save time, I am more and more confused, because Java reflection mechanism is very important and urgent, Therefore, I choose to watch videos + review other high-quality articles to focus on learning. If I want to write a blog that Xiaobai can understand, I also welcome your comments~

A foundation of Java reflection mechanism

1. Understanding reflection

If you pile up a pile of concepts as soon as you come up, Xiaobai will cry and the boss will be "tired".
Let's talk about its application scenario: we all know that the code we write in the compiler is often written - > compiled - > run. Careful people know that if we build the code, the corresponding code will be generated Class file, and then the generated The class file is loaded into the JVM through the class loader

That is, if my code is compiled and run, it will be generated The code behind the class object is "dead". Take an example in the crazy God Video: after the game match starts, someone opens the plug-in. How can the code in the plug-in be added dynamically and call the original code [without recompiling]? Similarly, sometimes after the program is compiled and run, we need to dynamically obtain the compiled objects. At this time, Java provides us with a solution: reflection

Java is a static language, but it has become a quasi dynamic language through reflection mechanism

2. Concept introduction

After the above simple understanding, let's simplify and clearly clarify the concept of reflection:

Reflection mechanism allows the program to obtain the internal information of any class with the help of reflection API during execution, and can operate the internal properties and methods of any object.

3. Application scenario

  1. At run time, you need to judge the class to which an object belongs
  2. At runtime, you need to judge the member variables and methods of a class
  3. You need to get generic information at run time
  4. You need to construct a class object at run time
  5. Call the member variables and methods of any object at run time
  6. Processing annotations at run time
  7. Generate dynamic proxy

II. Actual combat drill

1. Three ways to get Class

  • Pass class Forname() static method get
  • Get through the getClass() method of the instance
  • Get through the ". Class" attribute of the class

Example demonstration

package com.hang.reflection;

import com.hang.reflection.pojo.Animal;
import com.hang.reflection.pojo.Monkey;

public class ReflectionDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //1. Pass class Forname get
        Class class1 = Class.forName("com.hang.reflection.pojo.User");
        //2. Get through the getClass method of the instance
        Animal monkey=new Monkey("Golden Monkey",14.5,800);
        Class class2 = monkey.getClass();
        //3. Get through the ". Class" attribute of the class
        Class class3 = Animal.class;

        Class class4 = Monkey.class;

        //Judge whether the object belongs to the same Class through the hashCode between them
        System.out.println(class1.hashCode());
        System.out.println(class2.hashCode());
        System.out.println(class3.hashCode());
        System.out.println(class4.hashCode());
    }
}

Result analysis


The corresponding classes are obtained in three ways, and we notice that the second hashCode and the fourth hashCode are the same, indicating that a loaded class has only one class instance in the JVM.

2. Runtime structure and method of reflection acquisition

After obtaining the Class from the above three methods, it is an important part of reflection, because we can't consume resources and performance, just regain the Class class at runtime, but do some things that haven't been completed at compile time through the Class.

  • Get the name of the class
  • Get the properties of the class
  • Gets the value of the specified property
  • Method to get class
  • Gets the specified method of the class
  • Gets the constructor of the class
  • Gets the specified constructor of the class

code:

package com.hang.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class class1 = Class.forName("com.hang.reflection.pojo.User");

        /***Get the name of the class
         * 1.getName()Get: package name + class name
         * 2.getSimpleName():Get class name only
         */
        System.out.println(class1.getName());
        System.out.println(class1.getSimpleName());

        System.out.println("---------------------------");
        /***Get the properties of the class
         * 1.getFields():Only public attributes can be obtained
         * 2.getDeclaredFields():Can get all attributes
         */
        Field[] fields = class1.getFields();
        for (Field field : fields) {
            System.out.println("public:"+field);
        }
        Field[] declaredFields = class1.getDeclaredFields();

        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        System.out.println("------------------------------");

        /****Gets the value of the specified property
         * 1.getFiled(String name):The value of the specified public property was found
         * 2.getDeclaredFiled(String name):Find values for all specified properties
         */
//        Field name = class1.getField("name");
//        System.out.println(name);
        Field age = class1.getDeclaredField("age");
        System.out.println(age);

        System.out.println("------------------------------");

        /****Method to get class
         * 1.getMethods(): Get all public methods
         * 2.getDeclaredMethods(): Get all methods
         * ps:Note that the method obtained will also include the method of the parent class
         */
        Method[] methods = class1.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        Method[] declaredMethods = class1.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }

        System.out.println("------------------------------");

        /****Gets the specified method of the class
         * 1.getMethods(): Gets the specified public method
         * 2.getDeclaredMethods(): Gets the specified method
         */
        //String. Class -- > avoid ambiguity caused by overloading
        Method setName = class1.getMethod("setName", String.class);
        System.out.println(setName);

        System.out.println("-------------------------------");
        //If you get the specified method including private, you won't demonstrate it anymore

        /*****Gets the constructor of the class
         * 1.getConstructors():Gets the constructor of the public type in the class
         * 2.getDeclaredConstructors():Get all constructors of the class
         */
        Constructor[] constructors = class1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        System.out.println("---------------------------------");
        /****Gets the constructor of the specified type in the class
         * 1.getConstructor([xxx.class,xxx.class,...]);
         * 2.getDeclaredConstructor([xxx.class,xxx.class,...])
         */
        Constructor declaredConstructor = class1.getDeclaredConstructor(String.class,String.class,int.class);
        System.out.println(declaredConstructor);
    }
}

3. Practice of reflection application

Infinite loop is used to simulate the program in operation, and then dynamically generate objects and call methods through the reflection mechanism

package com.hang.reflection;

import com.hang.reflection.pojo.User;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;

public class ReflectionDemo3 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Scanner sc=new Scanner(System.in);
        System.out.println("1.Create an object; two.Get the parameterized constructor of the object; three.Call the specified method of the object; four.The specified parameters of the calling object; five.Exit program");
        Class class1=Class.forName("com.hang.reflection.pojo.User");
        User user2 = null;
        //Run time using loop simulator
        out:while(true){
            int choice=sc.nextInt();
            switch (choice){
                case 1:{
                    User user = (User) class1.newInstance();
                    System.out.println("A new object was created user,this user Information:"+user);
                    continue;
                }
                case 2:{
                    Constructor constructor = class1.getDeclaredConstructor(String.class, String.class, int.class);
                    user2 = (User) constructor.newInstance("Navigation", "1000", 22);
                    System.out.println("A new structure is constructed through a parametric constructor user,this user Information is:"+user2);
                    continue;
                }
                case 3:{
                    Method method = class1.getMethod("setName", String.class);

                    //Activate the resulting method
                    method.invoke(user2,"Hanghang 2");
                    System.out.println("After modifying user information user2:"+user2);
                    continue;
                }
                case 4:{
                    /**Operation properties by reflection
                     * Usually, the attribute of a class is private, so we can't operate it directly. Therefore, the following methods also operate the attribute through violence
                     * It is unsafe and is not recommended
                     */
                    Field id = class1.getDeclaredField("id");
                    //Enable permission to modify private
                    id.setAccessible(true);
                    id.set(user2,"1001");
                    System.out.println("After modifying user attributes user2:"+user2);
                    continue;
                }
                case 5:{
                    break out;
                }
            }
        }
    }
}

Operation results:

summary

It is very important to understand the reflection mechanism of Java. We should not only understand the application of reflection mechanism, but also have a certain understanding of its principle and JVM. After a relatively simple study of the reflection mechanism of Java, I will also post a brief blog about the proxy mode as a consolidation and share~

Topics: Java Back-end