java Foundation_ reflex

Keywords: Java

java Foundation_ reflex

**Reflection: * * reflection refers to classes that we can load, discover, and use during runtime that are completely unknown during compilation. Is a dynamic mechanism that allows us to command program instantiation, operate properties and call methods through strings. It makes the code more flexible, but it also brings more resource overhead.

After loading the Class, a Class object is generated in the heap memory, which contains the complete Class structure information. We can see the structure of the Class through this object. This object is like a mirror, through which we can see the structure of the Class. We vividly call it reflection.

Class 1:

  1. Class itself is also a class
  2. Class objects can only be created by the system
  3. A loaded Class has only one Class instance in the JVM
  4. A class object corresponds to a. Class file loaded into the JVM
  5. Each Class instance will remember which Class instance it was generated from
  6. All loaded structures in a Class can be completely obtained through Class
  7. Class is the root of Reflection. For any dynamically loaded and running class, you should first obtain the corresponding class object

Get class type instance:

  1. If a specific class is known, this method is the most reliable and the program performance is the highest through the class attribute of the class
  2. If the full Class name of a Class is known and the Class is under the Class path, it can be obtained through the static method forName() of Class class, and ClassNotFoundException may be thrown
  3. If an instance of a Class is known, call the getClass() method of the instance to obtain the Class object
  4. The built-in basic data type can directly use the class name. Type
  5. Using Class Loader
        // Method 1: obtained by object
		Student person = new Student();
        Class c1 = person.getClass();

        // Method 2: forname
        Class c2 = Class.forName("Student");

        // Method 3: obtained by class name. Class
        Class c3 = Student.class;

        // Method 4: wrapper classes of basic built-in types have a Type attribute
        Class c4 = Integer.TYPE;

        // Get parent type
        Class c5 = c1.getSuperclass();

Class 2 loading and ClassLoader:

  • Load: load the bytecode content of the class file into memory, convert these static data into methods to run-time data structures, and then generate a java.lang.Class object representing this class

  • Link: the process of merging the binary code of java classes into the running state of the JVM.

    • Verification: ensure that the loaded class information complies with the JVM specification and there are no security problems

    • Preparation: the stage of formally allocating memory for class variables and setting the default initial value of class variables. These memory will be allocated in the method area

    • Resolution: the process of replacing the symbolic reference (constant name) of the virtual machine constant pool with a direct reference (address)

  • initialization:

    • The process of executing a class constructor () method.
    • When initializing a class, if it is found that its parent class has not been initialized, you need to touch the initialization of its parent class first
    • Virtual chance ensures that the () methods of a class are locked and synchronized correctly in a multithreaded environment.
// When does the test class initialize
public class Test06 {
    static {
        System.out.println("Main Class is loaded");
    }

    public static void main(String[] args) {
        // 1. Active reference
        // Son son = new Son();
        // Reflection also produces active references
        try {
            Class.forName("Son");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
class Father{
    static {
        System.out.println("The parent class is loaded");
    }
}

class Son extends Father{
    static {
        System.out.println("Subclass loaded");
        m = 300;
    }
    static int m = 100;
    static final int M = 1;
}

When does class initialization occur?

Active reference of class (class initialization must occur)

  • When the virtual machine starts, initialize the class where the main method is located first
  • new is an object of a class
  • Call static members (except final constants) and static methods of the class
  • Use the methods of the java.lang.reflect package to make reflection calls to the class
  • When initializing a class, if its parent class is not initialized, its parent class will be initialized first

Passive reference of class (class initialization will not occur)

  • When accessing a static domain, only the class that actually declares the domain will be initialized
  • Defining class references through arrays does not initiate class initialization
  • Reference constants do not initialize this class

**Function of class loader: * * load classes into memory. There are boot class loader, extension class loader and system class loader.

public class Test07 {
    public static void main(String[] args) throws ClassNotFoundException {

        // Gets the loader of the system class
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        // Gets the parent class loader -- > extension class loader of the system class loader
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        // Gets the parent class loader -- > root loader of the extension class loader
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

        // Test which loader loads the current class
        ClassLoader classLoader = Class.forName("Test07").getClassLoader();
        System.out.println(classLoader);

        // Test who loaded the JDK built-in classes
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);

        // How to get the path that the system loader can load
        System.out.println(System.getProperty("java.class.path"));
        
        // Parental delegation mechanism
            // java.lang.String -->
    }
}

3 application of reflection:

3.1 get the complete structure of the runtime class:

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

public class Test08 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("User");

//        User user = new User();
//        c1 = user.getClass();

        // Get the name of the class
        System.out.println(c1.getName());  // Get package name + class name
        System.out.println(c1.getSimpleName()); // Get class name

        // Get the properties of the class
        System.out.println("+++++++++++++++++++++++++++++++");
        Field[] fields = c1.getFields();   // Only public properties can be found

        fields = c1.getDeclaredFields(); // Find all properties
        for(Field field: fields){
            System.out.println(field);
        }
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        // Method to get class
        System.out.println("+++++++++++++++++++++++++++++++++");
        Method[] methods = c1.getMethods(); // Get all public methods of this class and its parent class
        for(Method method: methods){
            System.out.println("natural:"+method);
        }
        methods = c1.getDeclaredMethods(); // Get all methods of this class
        for(Method method : methods){
            System.out.println("getDeclareMethods:"+method);
        }
        // Gets the specified method
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        // Gets the specified constructor
        System.out.println("+++++++++++++++++++++++++++");
        Constructor[] constructors = c1.getConstructors();
        for(Constructor constructor : constructors){
            System.out.println("#"+constructor);
        }
        constructors = c1.getDeclaredConstructors();
        for(Constructor constructor : constructors){
            System.out.println("#" + constructor);
        }
        // Gets the specified constructor
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println("appoint:"+declaredConstructor);
    }
}

3.2 performance comparison:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

// Analyze performance issues
public class Test10 {
    // Normal mode call
    public static void test01(){
        User user = new User();

        long startTime = System.currentTimeMillis();

        for(int i = 0; i < 1000000000;i++){
            user.getName();
        }
        long endTime = System.currentTimeMillis();

        System.out.println("1 billion times with common methods:"+(endTime-startTime)+"ms");
    }
    // Reflection mode call
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();

        Method getName = c1.getDeclaredMethod("getName", null);

        long startTime = System.currentTimeMillis();

        for(int i = 0; i < 1000000000;i++){
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();

        System.out.println("The reflection method is executed 1 billion times:"+(endTime-startTime)+"ms");
    }
    // Reflection mode call off detection
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();

        Method getName = c1.getDeclaredMethod("getName", null);
        getName.setAccessible(true);

        long startTime = System.currentTimeMillis();

        for(int i = 0; i < 1000000000;i++){
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();

        System.out.println("Close detection and execute 1 billion times:"+(endTime-startTime)+"ms");
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test01();
        test02();
        test03();
    }
}

3.3 get generics:

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

// Get generics through reflection
public class Test11 {
    public void test01(Map<String, User> map, List<User> list){
        System.out.println("test01");
    }

    public Map<String, User> test02(){
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Test11.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes =  method.getGenericParameterTypes();
        for (Type genericParameterType: genericParameterTypes){
            System.out.println("#" + genericParameterType);
            if(genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for(Type actualTypeArgument : actualTypeArguments){
                    System.out.println(actualTypeArgument);
                }
            }
        }

        method = Test11.class.getMethod("test02", null);
        Type genericReturnType =  method.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for(Type actualTypeArgument : actualTypeArguments){
                System.out.println(actualTypeArgument);
            }
        }
    }
}

3.4 obtaining annotation information:

import java.lang.annotation.*;
import java.lang.reflect.Field;

public class Test12 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("Student2");

        // Get annotations through reflection
        Annotation[] annotations = c1.getAnnotations();
        for(Annotation annotation : annotations){
            System.out.println(annotation);
        }

        // Gets the value of the annotation
        Tablekuang tablekuang = (Tablekuang)c1.getAnnotation(Tablekuang.class);
        String value = tablekuang.value();
        System.out.println(value);

        // Gets the annotation specified by the class
        Field f = c1.getDeclaredField("name");
        Filekuang annotation = f.getAnnotation(Filekuang.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());

    }
}
@Tablekuang("db_student")
class Student2{

    @Filekuang(columnName = "db_id", type = "int", length = 10)
    private int id;
    @Filekuang(columnName = "db_age", type = "int", length = 10)
    private int age;
    @Filekuang(columnName = "db_name", type = "varchar", length = 3)
    private String name;

    public Student2(){

    }

    public Student2(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}


// Annotation of class name
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tablekuang{
    String value();
}

// Attribute annotation
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Filekuang{
    String columnName();
    String type();
    int length();
}

Reference blog:

https://blog.csdn.net/weixin_45056780/article/details/105127722

Posted by james_byrne on Thu, 23 Sep 2021 00:53:18 -0700