Annotation and reflection

01. What is annotation

  • Annotation is from jdk5 New technologies introduced from 0
  • Function of Annotation
    • Not the program itself, you can explain the program (this is no different from comments)
    • It can be read by other programs (such as compiler, etc.)
  • Format of Annotation
    • Annotations exist in the code as @ annotation name. You can also add some parameter values, such as @ SuppressWarnings(value = "unchecked")
  • Where is Annotation used?
    • It can be attached to package,class,method,field, etc., which is equivalent to adding additional auxiliary information to them. We can access these metadata through reflection mechanism programming

02. Built in annotation

  • @Override: defined in Java In lang. override, this annotation is only applicable to modified methods, indicating that one method declaration intends to override another method declaration in the superclass.
  • Deprecated: defined in Java In lang. deprecated, this annotation can be used to modify methods, attributes and classes, indicating that programmers are not encouraged to use such elements, usually because it is dangerous or there are better choices
  • @SuppressWarnings: defined in Java Lang. SuppressWarnings, used to suppress warnings at compile time
    • @SuppressWarning("all")
    • @SuppressWarning("unchecked")
    • @SuppressWarnings(value={"unchecked","deprecation"})
    • ...
package com.chenchuyi.demo5;

public class TestAnnotation {

    public static void main(String[] args) {
        TestAnnotation.run();
    }

    //override method 
    @Override
    public String toString() {
        return super.toString();
    }

    //Programmers are not encouraged to use it, but it is still available
    @Deprecated
    public static void run(){
        System.out.println("How do you do");
    }
    
    //Suppress compiled warnings
    @SuppressWarnings("all")
    public void go(){
        System.out.println("123");
    }
}

03. Meta note

  • The function of meta annotation is to annotate other annotations. java defines four standard Mata annotation types, which are used to describe other annotation types.
  • These types and the classes they pay for are in Java Lang.annotation package (@ target, @ retention, @ docummented, @ inherited)
    • @Target: used to describe the scope of use of annotations (i.e. where the described annotations can be used)
    • @Retention: indicates where the annotation is still valid. It is used to describe the lifecycle of the annotation (source < class < runtime)
    • @Document: note that the annotation will be included in the javadoc
    • @Inherited: indicates that the subclass can inherit the annotation in the parent class

Custom annotation

package com.chenchuyi.demo5;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@mygo
public class metaAnnotation {
    
    @mygo
    public void goooo(){}
}

//Custom annotation
//METHOD is used in the METHOD
//TYPE is used in a class
@Target({ElementType.METHOD,ElementType.TYPE})
//RUNTIME>CLASS>SOURCE
@Retention(RetentionPolicy.RUNTIME)
@interface mygo{}

@The selectable values for Target are

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

@The selectable values for Retention are

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

04. Custom annotation

  • When you use @ interface to customize annotations, you automatically inherit Java lang.annotation. Annotation interface
  • analysis
    • @Interface is used to declare an annotation. Format: public @interface annotation name {definition content}
    • Each of these methods actually declares a configuration parameter
    • The name of the method is the name of the parameter
    • The return value type is the parameter type (the return value can only be the basic type, Class,String,enum)
    • You can declare the default value of the parameter through default
    • If there is only one parameter member, the general parameter name is value
    • An annotation element must have a value. When defining an annotation element, we often use an empty string with 0 as the default value
package com.chenchuyi.demo5;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class Annotation2 {

    @myAnnotation1(name = "1")
    public void run1(){}

    @myAnnotation2(19)
    public void run2(){}
}

//Custom annotation
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface myAnnotation1{
    //Annotated parameters: parameter type + parameter name ();
    //Define a string
    String name();
    //The default value will not be written in the comment
    int age() default 18;
    //Define an array
    int[] num() default {12,18};
}

//Custom annotation
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface myAnnotation2{
    //Annotated parameters: parameter type + parameter name ();
    //If only one parameter is defined, the parameter name can be written as values. The parameter name of value can be omitted for the parameter in the annotation. If multiple parameters are defined, they cannot be omitted
    int value();
}

05. Reflection overview

Dynamic language

  • **Dynamic language (weakly typed language) * * is a language that determines the data type only at run time. There is no need to declare the type of a variable before use. Usually, the value of a variable is the type of the value assigned. For example, Php, Asp, JavaScript, Python, Perl, and so on.
var s ="hello";
var i = 0;
var b = true;

Static language

  • **Static language (strongly typed language) * * is a language that can determine the data type of variables at compile time. Most static languages require that the data type of variables must be specified before using variables. For example, Java, C, C + +, C # and so on.
  • Java is not a dynamic language, but Java can be called a "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!
String s="hello";    //Variable of type String
boolean b=true;    //Variables of type boolean
int i=0;    //Variable of type int

Java Reflection

  • Java reflection mechanism is in the running state, for any class, you can know all the properties and methods of this class, and for any object, you can call any of its methods and properties. This dynamically obtained information and the function of dynamically calling the methods of the object are called the reflection mechanism of Java language.
  • After loading the Class, a Class object is generated in the method area of heap memory (a Class has only one Class 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. Therefore, we vividly call it reflection

06. Get reflection object

Functions provided by Java reflection mechanism

  • Determine the class of any object at run time
  • Construct an object of any class at run time
  • Judge the member variables and methods of any class at run time
  • Get generic information at run time
  • Call the member variables and methods of any object at run time
  • Processing annotations at run time
  • Generate dynamic proxy
  • . . .

Advantages and disadvantages of Java reflection

advantage:

  • It can dynamically create objects and compile, reflecting great flexibility

Disadvantages:

  • 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 s related to reflection

  • 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 a class
  • ...

Class class

This class is used to manipulate (reverse parse) the properties, methods, constructors, etc. of a class.

Person: name, age, address (as long as class knows your person class, it can know all your attributes, not only attributes, but even annotation on methods.)

public class Test01 {
    public static void main(String[] args) {
        try {
            Class<?> c1 = Class.forName("kuangJava.reflects.User");
            System.out.println(c1);
            Class<?> c2 = Class.forName("kuangJava.reflects.User");
            Class<?> c3 = Class.forName("kuangJava.reflects.User");
            System.out.println(c2.hashCode());
            System.out.println(c3.hashCode());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

//An entity class is a constructor with the or with theout parameters, such as get, set, and toString, as long as it has simple properties
class User {
    private int id;
    private String name;

    public User() {
    }


    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

output

class kuangJava.reflects.User
895328852
895328852

07. Several ways to get Class

Class class

  • The information that can be obtained after the object looks in the mirror: the properties, methods and constructors of a Class, and which interfaces a Class implements. For each Class, the JRE keeps an object of the same Class type for it. A Class object contains information about a specific structure (class/interface/enum/annotation/primitive type/void / [])

    • Class itself is also a class
    • Class objects can only be created by the system
    • A loaded Class has only one Class instance in the JVM
    • A class object corresponds to a class loaded into the JVM Class file
    • Each Class instance will remember which Class 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

    Get an instance of Class

    • If a specific class is known, it is obtained through the class attribute of the class. This method is the most safe and reliable, and the program performance is the highest

    Class clazz = Person.class;

    • If an instance of a Class is known, call the getClass() method of the instance to obtain the Class object

    Class clazz = person.getClass();

    • The full Class name of a Class is known, and the Class can be obtained through the static method forName() of Class class under the Class path, and ClassNotFoundException can be thrown

    Class clazz = Class.forName("demo01.Student");

    • The built - in basic data type can use the class name directly Type
    • You can also use ClassLoader (explained later)
package com.chenchuyi.demo5;

@SuppressWarnings("all")
public class getclassType {
    public static void main(String[] args) throws ClassNotFoundException {
        Person stu = new Student("Chen Chu");
        System.out.println("This is:"+stu.name);
        //Obtained by object
        Class c1 = stu.getClass();
        System.out.println(c1);
        //Obtained by forName
        Class c2 = Class.forName("com.chenchuyi.demo5.Student");
        System.out.println(c2);
        //By class name Class get
        Class c3 = Student.class;
        System.out.println(c3);
        //Wrapper classes of basic built-in types have a Type attribute
        Class c4 = Integer.TYPE;
        System.out.println(c4);
        //Get the parent class name from the child class name
        Class superclass1 = c1.getSuperclass();
        System.out.println(superclass1);
        Class superclass2 = c2.getSuperclass();
        System.out.println(superclass2);
    }
}

class Person{
    public String name;
    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

//student
class Student extends Person{
    public Student(String name) {
        super(name);
    }
}

//teacher
class Teacher extends Person{
    public Teacher(String name) {
        super(name);
    }
}

output

This is Chen Chu
class com.chenchuyi.demo5.Student
class com.chenchuyi.demo5.Student
class com.chenchuyi.demo5.Student
int
class com.chenchuyi.demo5.Person
class com.chenchuyi.demo5.Person

08. Class objects of all types

What types can have Class objects

  • Class: external class, member (member internal class, static internal class), local internal class, anonymous internal class
  • interface: interface
  • []: array
  • enum: Enumeration
  • Annotation: annotation @ interface
  • primitive type: basic data type
  • void
package com.chenchuyi.demo5;

import java.lang.annotation.ElementType;

@SuppressWarnings("all")
public class TestClass {
    public static void main(String[] args) {
        Class c1 = Object.class;//class
        Class c2 = Comparable.class;//Interface
        Class c3 = String[].class;//One dimensional array
        Class c4 = String[][].class;//Two dimensional array
        Class c5 = Override.class;//annotation
        Class c6 = ElementType.class;//enumeration
        Class c7 = Integer.class;//type
        Class c8 = void.class;//void
        Class c9 = Class.class;//Class

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);

        //As long as the element type (int) is the same as the dimension (one-dimensional or two-dimensional), it is the same Class
        int[] a = new int[10];
        int[] b = new int[100];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }
}

output

class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[Ljava.lang.String;
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
356573597
356573597

09. Class loading memory analysis

Class loading process

Class loading and ClassLoader understanding

  • Load: 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. Net file representing this class Lang.class object
  • 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 (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 a class constructor () method. The class constructor () method is generated by the combination of the assignment action of the compiler automatically collecting class variables and the statements in the static code block. (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, the initialization of its parent class needs to be triggered first
    • Virtual chance ensures that the () methods of a class are properly locked and synchronized in a multithreaded environment
public class Test05 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.n);
    }
}

class A {
    static {
        n = 300;
        System.out.println("A Class");
    }
    static int n = 100;
    {
        System.out.println("A Code block for class");
    }
    public A() {
        System.out.println("A Class construction method");
    }
}

output

A Class
A Code block for class
A Class construction method
100

10. Analysis 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 is an object of a class
    • Call static members (except final constants) and static methods of the class
    • Using Java 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
  • 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. For example, when the static variable of the parent class is referenced through the subclass, the subclass will not be initialized
    • Defining a class reference through an array does not trigger the initialization of this class
    • Reference constants do not trigger the initialization of this class (constants are stored in the constant pool of the class when they are linked)

The following five cases can be opened separately for practice

public class Test06 {
    static {
        System.out.println("Main Class is loaded");
    }

    public static void main(String[] args) {
        //1. Active reference
//        Son son = new Son();

        //2. Reflection also produces active references
//        try {
//            Class.forName("kuangJava.reflects.Son");
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }
        //A method that does not generate a reference to a class
        //3.
//        System.out.println(Son.b);
        //4.
//        Son[] sons = new Son[2];
        //5.
        System.out.println(Son.M);

    }
}

class Father {
    static int b = 2;
    static {
        System.out.println("Parent static code block");
    }
}

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

}

summary:
1.If you call constants of your own class through your own class, initialization will not occur
2.The subclass will not be initialized by calling the static variable or constant of the parent class through the subclass

output

1.
Main Class is loaded
 Parent static code block
 Static subclass code

2.
Main Class is loaded
 Parent static code block
 Subclass static code block

3.
Main Class is loaded
 Parent static code block
2

4.
Main Class is loaded

5.
Main Class is loaded
1

11. Class loader

Role of class loader

  • The function of class loading: load the bytecode content of the class file into memory, replace these static data with the runtime data structure of the method area, and then generate a Java. Net file representing this class in the heap Lang. class object, as the access entry of class data in the method area
  • Class caching: the standard Java se class loader can find 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 JVM garbage collection mechanism can recycle this class object

Role of class loader

class loader is used to load classes into memory. The JVM specification defines loaders for classes of the following types

public class Test07 {
    public static void main(String[] args) {
        //Get system class loader
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        System.out.println(classLoader);
        //Get the parent class loader of the system class loader -- extended class loader
        ClassLoader extendClassLoader = classLoader.getParent();
        System.out.println(extendClassLoader);
        //Get the parent class loader of the extension class loader -- root loader (C + +)
        ClassLoader rootClassLoader = extendClassLoader.getParent();
        System.out.println(rootClassLoader);


        try {
            //Gets which loader loaded the current class
            ClassLoader classLoader1 = Class.forName("kuangJava.reflects.Test07").getClassLoader();
            System.out.println(classLoader1);
            //Get which loader loaded the JDK built-in class
            ClassLoader classLoader2 = Class.forName("java.lang.Object").getClassLoader();
            System.out.println(classLoader2);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //How to get the loading path of the system class loader
        //System.out.println(System.getProperty("java.class.path"));
        /**
         * D:\software\Java\jdk1.8.0_241\jre\lib\charsets.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\deploy.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\access-bridge-64.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\cldrdata.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\dnsns.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\jaccess.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\jfxrt.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\localedata.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\nashorn.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\sunec.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\sunjce_provider.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\sunmscapi.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\sunpkcs11.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\ext\zipfs.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\javaws.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\jce.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\jfr.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\jfxswt.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\jsse.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\management-agent.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\plugin.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\resources.jar
         * D:\software\Java\jdk1.8.0_241\jre\lib\rt.jar
         * D:\IdeaProjects\mystudy\target\classes
         * D:\mavenRepository\org\apache\httpcomponents\httpclient\4.5.12\httpclient-4.5.12.jar
         * D:\mavenRepository\org\apache\httpcomponents\httpcore\4.4.13\httpcore-4.4.13.jar
         * D:\mavenRepository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar
         * D:\mavenRepository\commons-codec\commons-codec\1.11\commons-codec-1.11.jar
         * D:\mavenRepository\org\apache\poi\poi\4.1.2\poi-4.1.2.jar
         * D:\mavenRepository\org\apache\commons\commons-collections4\4.4\commons-collections4-4.4.jar
         * D:\mavenRepository\org\apache\commons\commons-math3\3.6.1\commons-math3-3.6.1.jar
         * D:\mavenRepository\com\zaxxer\SparseBitSet\1.2\SparseBitSet-1.2.jar
         * D:\mavenRepository\org\apache\poi\poi-ooxml\4.1.2\poi-ooxml-4.1.2.jar
         * D:\mavenRepository\org\apache\poi\poi-ooxml-schemas\4.1.2\poi-ooxml-schemas-4.1.2.jar
         * D:\mavenRepository\org\apache\xmlbeans\xmlbeans\3.1.0\xmlbeans-3.1.0.jar
         * D:\mavenRepository\org\apache\commons\commons-compress\1.19\commons-compress-1.19.jar
         * D:\mavenRepository\com\github\virtuald\curvesapi\1.06\curvesapi-1.06.jar
         * D:\mavenRepository\com\alibaba\fastjson\1.2.73\fastjson-1.2.73.jar
         * D:\mavenRepository\commons-io\commons-io\2.8.0\commons-io-2.8.0.jar
         * D:\software\ideaIU-2019.3.3.win\lib\idea_rt.jar
         */
    }
}

output

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@355da254
null
sun.misc.Launcher$AppClassLoader@18b4aac2
null

12. Get the runtime structure of the class

Gets the complete structure of the runtime class

Get the complete structure of the runtime class through reflection

Field Method Construtor Superclass Interface Annotation

  • All interfaces implemented
  • Inherited parent class
  • All constructors
  • All methods
  • All fields
  • annotation
  • . . .
public class Test08 {
    public static void main(String[] args) {
        try {
            Class<?> c1 = Class.forName("kuangJava.reflects.User");
            //Gets the name of the class
            System.out.println(c1.getName());  //Get package name + class name
            System.out.println(c1.getSimpleName());
            System.out.println("========");  //Class name
            
            //Gets the properties of the class
            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 nameField = c1.getDeclaredField("name");//--Gets the value of the specified property
            System.out.println(nameField);
            
            //Method to get class
            Method[] methods = c1.getMethods(); //--Get all public methods of this class and its parent class
            for (Method method : methods) {
                System.out.println("===getMethods==="+method);
            }
            methods = c1.getDeclaredMethods(); //Get all methods of this class
            for (Method method : methods) {
                System.out.println("===getDeclaredMethods==="+method);
            }
            Method getName = c1.getDeclaredMethod("getName", null); //--Gets the specified method
            Method setName = c1.getDeclaredMethod("setName", String.class);
            System.out.println(getName);
            System.out.println(setName);
            
            //Gets the specified constructor
            Constructor<?>[] constructors = c1.getConstructors(); //Get all constructors of public
            for (Constructor<?> constructor : constructors) {
                System.out.println("===getConstructors==="+constructor);
            }
            constructors = c1.getDeclaredConstructors();//Gets the constructor of this class
            for (Constructor<?> constructor : constructors) {
                System.out.println("===getDeclaredConstructors==="+constructor);
            }
            Constructor<?> declaredConstructor = c1.getDeclaredConstructor(int.class, String.class);//Gets the specified constructor
            System.out.println("Specify constructor:"+declaredConstructor);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

class User {
    private int id;
    private String name;

    public User() {
    }

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

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    private void test() {

    }
}

output

kuangJava.reflects.User
User
========
private int kuangJava.reflects.User.id
private java.lang.String kuangJava.reflects.User.name
private java.lang.String kuangJava.reflects.User.name
===getMethods===public java.lang.String kuangJava.reflects.User.getName()
===getMethods===public int kuangJava.reflects.User.getId()
===getMethods===public void kuangJava.reflects.User.setName(java.lang.String)
===getMethods===public void kuangJava.reflects.User.setId(int)
===getMethods===public final void java.lang.Object.wait() throws java.lang.InterruptedException
===getMethods===public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
===getMethods===public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
===getMethods===public boolean java.lang.Object.equals(java.lang.Object)
===getMethods===public java.lang.String java.lang.Object.toString()
===getMethods===public native int java.lang.Object.hashCode()
===getMethods===public final native java.lang.Class java.lang.Object.getClass()
===getMethods===public final native void java.lang.Object.notify()
===getMethods===public final native void java.lang.Object.notifyAll()
===getDeclaredMethods===public java.lang.String kuangJava.reflects.User.getName()
===getDeclaredMethods===public int kuangJava.reflects.User.getId()
===getDeclaredMethods===public void kuangJava.reflects.User.setName(java.lang.String)
===getDeclaredMethods===private void kuangJava.reflects.User.test()
===getDeclaredMethods===public void kuangJava.reflects.User.setId(int)
public java.lang.String kuangJava.reflects.User.getName()
public void kuangJava.reflects.User.setName(java.lang.String)
===getConstructors===public kuangJava.reflects.User()
===getConstructors===public kuangJava.reflects.User(int,java.lang.String)
===getDeclaredConstructors===public kuangJava.reflects.User()
===getDeclaredConstructors===public kuangJava.reflects.User(int,java.lang.String)
Specify constructor: public kuangJava.reflects.User(int,java.lang.String)

13. Dynamically create object execution methods

What can I do with a Class object?

  • Create Class object: call newInstance() method of Class object
    • Class must have a parameterless constructor
    • The constructor of the class must have sufficient access rights

Think: can't you create an object without a parameterless constructor? 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

Call the specified method

Through reflection, the Method in the class is called and implemented through the Method class

  1. Get a Method object through the getMethod(String name, Class... parameterTypes) Method of Class class, and set the parameter type required for this Method operation.
  2. 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

Object invoke(Object obj, Object... args)

  • Object corresponds to the return value of the original method. If the original method has no return value, null is returned
  • If the original method is static, the formal parameter Object obj can be null
  • If the original method parameter list is empty, Object... args is null
  • If the original method is declared as private, you need to explicitly call the setAccessible(true) method of the method object before calling the invoke() method to access the private method

setAccessible

  • Method, Field and Constructor objects all have setAccessible() methods
  • setAccessible is a switch that enables and disables scheme 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 the original private members inaccessible
  • If the parameter value is false, it indicates that the reflected object should implement java language access check
public class Test09 {
    public static void main(String[] args) {
        try {
            //Get Class object
            Class c1 = Class.forName("kuangJava.reflects.User");
            //1. Construct an object (essentially calling the class's parameterless constructor)
//            User user = (User) c1.newInstance();
//            System.out.println(user);
            //2. Create objects through constructors
//            Constructor constructor = c1.getDeclaredConstructor(int.class, String.class);
//            User user2 = (User) constructor.newInstance(18, "zyy");
//            System.out.println(user2);
            //3. Call common methods through reflection
            User user3 = (User) c1.newInstance();
            //Get a method by reflection
            Method setName = c1.getDeclaredMethod("setName", String.class);
            //invoke: the meaning of activation (object, "method value")
            setName.invoke(user3, "zyy");
            System.out.println(user3.getName());
            //Reflection static method
            Method print = c1.getDeclaredMethod("print", String.class);
            print.invoke(null, "hello");
            //4. Operate attributes through reflection
            User user4 = (User) c1.newInstance();
            Field name = c1.getDeclaredField("name");
            //Private properties cannot be operated directly. We need to turn off the security monitoring of the program, and setAccessible(true) of properties or methods
            name.setAccessible(true);
            name.set(user4, "zyy2");
            System.out.println(user4.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

class User {
    private int id;
    private String name;

    public User() {
    }

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

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    private void test() {

    }

    public static void print (String msg) {
        System.out.println("print:"+msg);
    }

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

14. Performance comparison and analysis

package com.chenchuyi.demo7;

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

public class TestTime {

    //Common method
    public static void test01() {
        Users users = new Users();
        long starttime = System.currentTimeMillis();
        for (int i = 0; i <= 1000000000; i++) {
            users.run(18);
        }
        long endtime = System.currentTimeMillis();
        System.out.println("General:"+(endtime - starttime)+"ms");
    }

    //reflex
    public static void test02() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Users users = new Users();
        Class c1 = users.getClass();
        Method run = c1.getDeclaredMethod("run",int.class);
        long starttime = System.currentTimeMillis();
        for(int i = 0;i<=10000000;i++){
            run.invoke(users,18);
        }
        long endtime = System.currentTimeMillis();
        System.out.println("Reflection:"+(endtime - starttime)+"ms");
    }

    //The reflection method closes the detection program
    public static void test03() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Users users = new Users();
        Class c1 = users.getClass();
        Method run = c1.getDeclaredMethod("run",int.class);
        run.setAccessible(true);
        long starttime = System.currentTimeMillis();
        for(int i = 0;i<=10000000;i++){
            run.invoke(users,18);
        }
        long endtime = System.currentTimeMillis();
        System.out.println("reflex+close:"+(endtime - starttime)+"ms");
    }

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

output

Normal: 8 ms
 Reflection: 76 ms
 reflex+Off: 73 ms

15. 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,GenericArrayType,TypeVariable and WildcardType to represent types that cannot be classified into Class but have the same name as the original type
  • ParameterizedType: represents a parameterized type, such as Collection
  • GenericArrayType: indicates that an element type is an array type of parameterized type or type variable
  • TypeVariable: it is the public parent interface of various types of variables
  • WildcardType: represents a wildcard type expression
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) {
        try {
            System.out.println("Print test01 Generics of method parameters");
            Method method = Test11.class.getDeclaredMethod("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);
                    }
                }
            }

            System.out.println("Print test02 Generic type of return value");
            method = Test11.class.getDeclaredMethod("test02");
            Type genericReturnType = method.getGenericReturnType();
            System.out.println("#"+genericReturnType);
            if (genericReturnType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }
}

output

Print test01 Generics of method parameters
#java.util.Map<java.lang.String, kuangJava.reflects.User>
class java.lang.String
class kuangJava.reflects.User
#java.util.List<kuangJava.reflects.User>
class kuangJava.reflects.User
 Print test02 Generic type of return value
#java.util.Map<java.lang.String, kuangJava.reflects.User>
class java.lang.String
class kuangJava.reflects.User

16. Get annotation information

Reflection operation annotation

  • getAnnotations
  • getAnnotation

package com.chenchuyi.demo7;

import org.omg.Messaging.SYNC_WITH_TRANSPORT;

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

@SuppressWarnings("all")
public class getAnnotation {
    public static void main(String[] args) throws NoSuchFieldException {
        //Get annotations through reflection
        Class c1 = test.class;
        Annotation[] annotations = c1.getAnnotations();
        for(Annotation annotation : annotations){
            System.out.println("Get annotations through reflection:"+annotation);
            //Gets the value of the annotated value
            if(annotation instanceof TableStudent){
                System.out.println("Get the value of the annotation through reflection:"+((TableStudent) annotation).value());
            }
        }

        //Gets the annotation specified by the class
        Field name = c1.getDeclaredField("name");
        FieldStudent annotation = name.getAnnotation(FieldStudent.class);
        System.out.println("Get the annotation specified by the class:"+annotation.columnName());
        System.out.println("Get the annotation specified by the class:"+annotation.length());
        System.out.println("Get the annotation specified by the class:"+annotation.type());
    }
}

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

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

@TableStudent("db_Student")
class test{
    @FieldStudent(columnName = "id", type = "int", length = 30)
    private int id;
    @FieldStudent(columnName = "name", type = "varchar", length = 20)
    private String name;
    @FieldStudent(columnName = "age", type = "int", length = 3)
    private int age;

    public test() {}

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

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

output

Get annotations through reflection:@com.chenchuyi.demo7.TableStudent(value=db_Student)
Get the value of the annotation through reflection: db_Student
 Get the annotation specified by the class: name
 Get the annotation specified by the class: 20
 Get the annotation specified by the class: varchar

Keywords: Java JavaEE JavaSE jar

Added by mattcass on Tue, 04 Jan 2022 13:29:40 +0200