JAVA annotation and reflection 2 {reflection mechanism} JAVA starts from the foundation -- 4

Reflection mechanism

+JVM explains creating objects at runtime (classLoader)

Overview of java reflection mechanism

Dynamic language-------------------------------------------------------------------------
◆ it is a kind of language that can change its structure at run time: for example, new functions, objects and even code can be introduced, existing functions can be deleted or other structural changes. Generally speaking, the code can change its structure according to some conditions at run time
◆ main dynamic languages: Object-C, c#, Javascript, PHP, Python, etc.
Static language-------------------------------------------------------------------------
◆ corresponding to dynamic language, the language with immutable runtime structure is static language. Such as Java, C, C + +.
◆ Java is not a dynamic language, but Java can be called "quasi dynamic language". That is, Java has certain dynamics. We can use reflection mechanism to obtain characteristics similar to dynamic language. The dynamic nature of Java makes programming more flexible

Java Reflection -- Reflection Mechanism

◆ reflection is the key to Java being regarded as a dynamic language. The reflection mechanism allows the program to obtain the internal information of any class with the help of Reflection APLI during execution, and can directly operate the internal properties and methods of any object.
Class c=Class forname(java. lang String")
Class class is the core class of management reflection - Object also has a getClass()
◆ after loading the Class, an object of Class type is generated in the method area of heap memory (a Class has only one Cass object), 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, so we vividly call it reflection
Normal method: import the required "package class" – > name and obtain the instantiated object through new instantiation – >
Reflection method: instantiate the object – > getClass () method – > get the complete "package class" name

Research and application of Java reflection mechanism

Functions provided by Java reflection mechanism
◆ judge the class of any object at runtime
◆ construct the object of any class at runtime
◆ judge the member variables and methods of any class at run time
◆ get generic information at runtime
◆ call the member variables and methods of any object at runtime
◆ handling annotations at runtime
◆ generate dynamic agents

advantage

It can be compiled dynamically to reflect flexibility

shortcoming

It has an impact on performance. Using reflection is basically an interpretation operation. We can tell the JVM what we want to do and it meets our requirements. Such operations are always slower than performing the same operation directly.

Main api

java. lang Class: represents a class
java lang reflect Method: represents the method of the class
java lang. reflect Field: represents the member variable of the class
java. lang reflect Constructor: represents the constructor of the class

Class class

◆ the following methods are defined in the object class, which will be inherited by all subclasses
public final Class getclasso
◆ the type of the return value of the above method is a Cass class, which is the source of Java reflection. In fact, the so-called reflection is well understood from the running results of the program,
That is, you can find the name of the class through object reflection

◆ information that can be obtained after the object looks in the mirror: the attributes, methods and constructors of a class, and which interfaces a class implements. For each class, JRE reserves an object of the same Cass type. A Cass object contains information about a specific structure (class/interface/enum/ annotation/primitive type/od).
◆ Cass itself is also a class
◆ Cass objects can only be created by the system
◆ a loaded class will only have one Cass instance in the JVM
◆ a Cass object corresponds to a class file loaded into the JVM
◆ the instance of each class will remember which Cass instance it was generated from
◆ all loaded structures in a Class can be completely obtained through Class
◆ Class is the root of Reflection. For any Class you want to dynamically load and run, you have to obtain the corresponding Class object first

Common methods of Class

Method nameFunction description
static Classforname(String name)Returns the Class object with the specified Class name
Object newlnstance()Call the default constructor to return an instance of the Class object
getName()Returns the name of the entity (class, interface, array class or void) represented by this Cass object
Class getSuperClass()Returns the CASS object of the parent class of the current Cass object
Class[] getinterfaces()Gets the interface of the current Class object
ClassLoader getClassLoader()Returns the class loader for this class
Constructor[] getConstructors()Returns an array containing some Constructor objects
Method getMothed( String name, Class.T)Returns a Method object whose formal parameter type is paramType
Field[] getDeclaredFelds()Returns an array of Feld objects

What types can have Cas objects?

Class: external class, member (member internal class, static internal class), local internal class, anonymous internal class.
interface: interface
[]: array
Enum: enum
Annotation: annotation @ interface
primitive type: basic data type
void

The object and array heap where Java memory analysis stores new can be shared by all threads without storing other object references. The variables that store the basic variable type (which will contain the specific value of the basic type) the Java memory stack reference object (which will store the specific address of the reference in the heap) can be shared by all threads. The method area contains all class and static variables

Class loading and Classloader understanding
◆ loading: load the bytecode content of Cass into memory, convert these static data into the runtime data structure of the method area, and then generate a Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java Lang. class object
◆ link: the process of merging the binary code of Java class into the running state of MM.

◆ verification: ensure that the loaded class information complies with the L M specification and there are no security problems
◆ preparation: the stage of formally allocating memory for class variables (static) 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) in the virtual machine constant pool with a direct reference (address)

◆ initialization

◆ the process of executing the class constructor < clinit > (method. The class constructor < clinit > () method is generated by automatically collecting the assignment actions of all class variables in the class and combining the statements in the static code block during compilation. (the class constructor is used to construct class information, not the constructor to construct the class object.).
◆ when initializing a class, if it is found that its parent class has not been initialized, it is necessary to trigger the initialization of its parent class first.
◆ virtual opportunity ensures that the < clinit > (method of a class is locked and synchronized correctly in a multithreaded environment.

#Class initialization

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 - object of a class
◆ call static members (except final constants) and static methods of the class
◆ use jjava The method of Lang reflect package makes reflection calls to the class
◆ when initializing a class, if its parent class is not initialized, its parent class will be initialized first

package main.Reflection;

//Active reference to class -- class initializes
public class Test06 {
    static {
        System.out.println("main Method is loaded");
    }

    public static void main(String[] args) throws ClassNotFoundException {
//        Son son = new Son();
//Reflections also produce references
        Class.forName("main.Reflection.Son");
    }
}

class Father {
    static int b = 2;

    static {
        System.out.println("The parent class is being loaded");
    }
}

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

    static int m = 100;
    static final int M = 1;
}

Passive reference of class (class initialization will not occur)

When accessing a static domain, only
Classes that truly declare this domain will be initialized. For example, when the ◆ static variable of the parent class is referenced through the subclass, the subclass initialization will not be caused
◆ defining a class reference through an array will not trigger the initialization of this class
◆ reference constants will not trigger the initialization of this class (constants are stored in the constant pool of the calling class in the link phase)

Role of class loader

◆ function of class loading: load the bytecode content of the class file into memory, convert these static data into the runtime data structure of the method area, and then generate a java.xml file representing this class in the heap Lang (class) object, which serves as the access entry for class data in the method area.
◆ class cache: the standard Javase class loader can search for classes as required, but once a class is loaded into the class loader, it will remain loaded (cached) for a period of time. However, the M garbage collection mechanism can recycle these Cass objects

◆ Java Classloader (English: Java Classloader) is a part of Java Runtime Environment, which is responsible for dynamically loading Java classes into the memory space of Java virtual machine. Classes are usually loaded on demand, that is, when the class is first used. Thanks to the class loader, the Java runtime system does not need to know the file and file system. When learning class loaders, it is important to master the concept of Java delegation.
Each Java class must be loaded into memory by a class loader. Java programs can take advantage of external libraries (that is, software libraries written by other authors).
◆ there are three default class loaders in the JVM:
◆1. Bootstrap class loader. It is written by native code (such as C language) and does not inherit from Java lang.ClassLoader. Be responsible for loading the core Java library and storing it in < Java_ Home > / JRE / lib directory.
◆2. Extensions class loader. Used in < Java_ Home > / JRE / lib / ext, or Java Load the Java extension library in the directory indicated in ext.dirs. The implementation of the Java virtual machine provides an extension library directory. The class loader finds and loads Java classes in this directory. This class is created by sun misc. Launcher $extclassloader implementation.

◆3.Apps class loader (also known as system class loader). Load Java classes according to the class path of the Java application (java.class.path or CLASSPATH environment variable). Generally speaking, Java application classes are loaded by it. You can use classloader Getsystemclassloader() to get it. This class is created by sun misc. Launcher $appclassloader implementation.
◆ each class loader has a parent class loader.

package main.Reflection;


public class Test07 {
    public static void main(String[] args) throws ClassNotFoundException {
        //Get system class loader
//        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);
//        //Get the parent class loader of the extension class loader -- root loader (c,c + +)
//        ClassLoader parent1 = parent.getParent();
//        System.out.println(parent1);
//
//        //Test which loader loads the current class
//        ClassLoader classLoader = Class.forName("main.Reflection.Test07").getClassLoader();
//        System.out.println(classLoader);
//       //Test which loader loads the jdk built-in classes
//        ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
//        System.out.println(classLoader1);
//
//
        //How to get the loading path of the system class loader
        String property = System.getProperty("java.class.path");
        System.out.println(property);
        //Dual delegation mechanism
           //java. Lang.string -- > user class loader -- > root loader
          //If you write a Java Lang. string, will not run, but will find the on the root loader to use
        /**
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\charsets.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\deploy.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\access-bridge-64.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\cldrdata.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\dnsns.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\jaccess.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\jfxrt.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\localedata.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\nashorn.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\sunec.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\sunjce_provider.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\sunmscapi.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\sunpkcs11.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\zipfs.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\javaws.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\jce.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\jfr.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\jfxswt.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\jsse.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\management-agent.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\plugin.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\resources.jar;
         * C:\Program Files\Java\jdk1.8.0_301\jre\lib\rt.jar;
         * E:\obj\ideaObj\annotation\out\production\annotation;
         * D:\idear\IntelliJ IDEA 2021.2\lib\idea_rt.jar
         */
        
        
    }
}

Create an object for the runtime class

Get the complete structure of the runtime class through reflection
Field, Method, Constructor, Superclass, Interface, Annotation

All interfaces implemented
Inherited parent class
All constructors
All methods
All fields
annotation

package main.Reflection;

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

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

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

        //Get the name of the class
        System.out.println(c1.getName());//Package name plus class name
        System.out.println(c1.getSimpleName());//Class name

        //Get the properties of the class
        System.out.println("===========Properties of class=========");
        Field[] fields = c1.getFields();//Only public properties can be found
//        for (Field field : fields) {
//            System.out.println(field);//  Can't print out
//        }
        fields = c1.getDeclaredFields();//All properties found
        for (Field field : fields) {
            System.out.println(field);
        }
        Field name = c1.getDeclaredField("name");//Find private name from all properties
//        Field name1 = c1.getField("name");// Only public attribute can be found. There is no public name attribute
        System.out.println(name);

        //Acquisition method
        System.out.println("===========getMethods=========");
        Method[] methods = c1.getMethods();// Get all public methods of this class and its parent class
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("===========getDeclaredMethods=========");

        Method[] methods1 = c1.getDeclaredMethods();//Get all methods of this class
        for (Method method : methods1) {
            System.out.println(method);
        }


    }

}

In the actual operation, the operation code to obtain the class information is not often developed.
Be familiar with Java Function of Lang reflect package and reflection mechanism.
How to get the names and modifiers of properties, methods and constructors.

Dynamically create object execution methods

Create Class object: call the newlnstance() method of Class object
– 1) class must have a parameterless constructor.
– 2) the access rights of the constructor of the class need to be sufficient

As long as the constructor in the class is explicitly called during the operation and the parameters are passed in, the operation can be instantiated.
The steps are as follows
– 1) get the constructor of the specified parameter type of this Class through getdeclaraedconstructor (Class.... parameterTypes) of Class class
– 2) pass an object array into the formal parameters of the constructor, which contains all the parameters required by the constructor.
3) Instantiate objects through Constructor

	package main.Reflection;

import java.lang.reflect.Field;

//Dynamically create objects through reflection
public class Test09 {

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //Get Class object
        Class c1= Class.forName("main.Reflection.User");

        //Construct an object
        User user = (User)c1.newInstance();//Call parameterless constructor
        System.out.println(user);

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

        User user1 = (User)c1.newInstance();//Call parameterless constructor
        Field name = c1.getDeclaredField("name");

        //Private properties cannot be operated directly. You need to close the program's security detection setAccessible(true)
        name.setAccessible(true);//Permission checking invalidates private. false is not enabled by default, and true is enabled
        name.set(user1,"pupil");
        System.out.println(user1.getName());

    }
}

Call the specified method

Through reflection, the Method in the class is called and completed through the Method class
① Get a Method object through the getmethod (string name, Class. Parameter types) Method of Class class, and set the parameter type required for this Method operation.
② Then use object invoke (object obj, object [] args) to call and pass the parameter information of the obj object to be set to the method.

setAccessible

Method, Fieid and Constructor objects all have setAccessible()
The setAccessible() method is used to enable and disable access security checks
If the parameter value is true, it indicates that the Java language access check should be cancelled when the reflected object is used
– improve the efficiency of reflection. If reflection must be used in the code, and the code of this sentence needs to be called frequently, please set it to true.
– make private members that cannot be accessed can also be accessed
If the parameter value is false, it indicates that the reflected object should implement Java language access check

Performance test

package main.Reflection;

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("Normal execution getName Time required for billions of times:" + (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("Reflection mode execution getName Time required for billions of times:" + (endTime - startTime) + "ms");
    }

    //Reflection mode call
    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("Turn off detection reflection mode execution getName Time required for billions of times:" + (endTime - startTime) + "ms");
    }


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

Get generic information

Reflection operation generics

Java uses the generic erasure mechanism to introduce generics. Generics in Java are only used by the compiler javac to ensure data security and avoid forced type conversion. However, once the compilation is completed, all types related to generics are erased
In order to manipulate these types through reflection, Java adds parameterizedtype and genericarray type. TypeVariable and WildcardType are several types to represent types that cannot be classified into Class but have the same name as the original type
Parametrizedtype: indicates a parameterized type; For example, collection < string >
GenericArrayType: indicates that - element types are parameterized types or array types of type variables
TypeVariable: it is the public parent interface of various types of variables
WildcardType: represents a wildcard type expression

package main.Reflection;

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("01");
    }

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

    public static void main(String[] args) throws NoSuchMethodException {
        Method me = Test11.class.getMethod("test01", Map.class, List.class);

        Type[] genericParameterTypes = me.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);
                }
            }
        }

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

Get annotation information

Reflection operation annotation
getAnnotations
getAnnotation

package main.Reflection;

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

//Contact reflection operation annotation
public class Test12 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("main.Reflection.Student2");
        //Get annotations through reflection

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

        //Get the value of annotation value
        TableCloud tableCloud = (TableCloud) c1.getAnnotation(TableCloud.class);
        String value = tableCloud.value();
        System.out.println(value);

        //Gets the annotation specified by the class
        Field f = c1.getDeclaredField("id");
        FieldCloud annotation = f.getAnnotation(FieldCloud.class);
        System.out.println(annotation.conlumnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }


}

@TableCloud("db_student")
class Student2 {
    @FieldCloud(conlumnName = "db_id", type = "int", length = 10)
    private int id;
    @FieldCloud(conlumnName = "db_age", type = "int", length = 10)
    private int age;
    @FieldCloud(conlumnName = "db_name", type = "String", 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;
    }
}


//Class name annotation
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableCloud {
    String value();
}

//Attribute annotation
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldCloud {
    String conlumnName();

    String type();

    int length();
}

Keywords: Java Programming Back-end

Added by NewfieBilko on Fri, 21 Jan 2022 11:33:50 +0200