Annotation and reflection

annotation

Annotation

Introduction to annotation

  • Can be read by other programs
  • Format: @ + annotation name
  • Usage: it can be attached to package, class, method, field, etc., which is equivalent to adding auxiliary information to access the content under the annotation through the reflection mechanism

Built in annotation

  • @Override: defined in Java In lang. override, this annotation is only applicable to rhetoric, 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 for rhetoric, attributes, and classes to indicate that programmers are not encouraged to use such elements, usually because it is dangerous or there are better choices
  • @SuppressWarnings: defined in Java In lang. SuppressWarnings, positive pressure warning is used to suppress the warning information during compilation Different from the previous two comments, you need to add a parameter to use it correctly. These parameters have been defined. We can use them selectively
    • @SuppressWarings("all")
    • @SuppresSWarnings("unchecked")
    • @SuppressWarnings(value={"unchecked" ,"deprecation"})
      wait.

Meta annotation

  • Responsible for annotation and other annotations
  • Java defines four standard meta annotation types
    • @Target
    • @Retention
    • @Documented
    • @Inherited
@Target

@Target: used to describe the scope of use of annotations (i.e. where the described annotations can be used)

//Test meta annotation
public class Test02 {
    
    @MyAnnotation
    public void test(){
        
    }
}
//Define an annotation
//Indicates where annotations can be used
@Target( value = ElementType.METHODE)
@interface MyAnnotation{
    
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    /* Class, interface (including annotation type) or enumeration declaration  */
    TYPE,

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

    /** Method declaration */
    /*Methodologically   */
    METHOD,

    /** Formal parameter declaration */
    /* Parameter declaration  */
    PARAMETER,

    /** Constructor declaration */
     /* Construction method declaration  */
    CONSTRUCTOR,

    /** Local variable declaration */
     /* Local variable declaration  */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
     /* Annotation type declaration  */
    ANNOTATION_TYPE,

    /** Package declaration */
     /* Package declaration  */
    PACKAGE,

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

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

@Retention: indicates the level at which the annotation information needs to be saved. It is used to describe the annotation life cycle

  • (SOURCE < CLASS < RUNTIME)
  • Retention.java
//Test meta annotation
public class Test02 {
    
    @MyAnnotation
    public void test(){
        
    }
}

//Indicates at what stage our annotation is still valid
//runtime>class>sources
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    /* Annotation The information only exists during the compiler processing, and there is no Annotation information after the compiler processing  */
    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.
 */
    /* The compiler stores the Annotation in the corresponding of the class Class file. 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
 */
/* The compiler stores the Annotation in a class file and can be read in by the JVM */
RUNTIME
@Documented

@Document: note that the annotation will be included in Javadoc

//Test meta annotation
public class Test02 {
    
    @MyAnnotation
    public void test(){
        
    }
}

//Documented indicates whether our annotations are generated in Javadao
@Documented
@interface MyAnnotation{
    
}
@Inherited

@Inherited: indicates that the subclass can inherit the annotation in the parent class

//Test meta annotation
public class Test02 {
    
    @MyAnnotation
    public void test(){
        
    }
}
//The subclass can inherit the annotation of the parent class
@Inherited
@interface MyAnnotation{
    
}

Custom annotation

  • java.lang.annotation.Annotation interface
  • Use @ interface to customize annotations
  • 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 type of parameter (return value can only be 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
//Custom annotation
public class Test03 {
    //Annotations can display assignments. If there is no default value, we must assign a value to the annotation
    @MyAnnotation2(name = "kaysen",age = 10)
    public void test(){
        
    }
    @MyAnnotation3(3)
    public void test2(){

    }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    //Annotated parameters: parameter type + parameter name ();
    String name() default "";
    int age() default 0;
    int id() default -1;//The default value is - 1, which means it does not exist

    String[] schools() default {"tsinghua","Peking University"};
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
   int value();//If there is only one value, it can be named value. The annotation can omit value and assign value directly
}

reflex

Static language VS dynamic language

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 runtime code can change its structure according to some conditions.
    • 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 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!

Java Reflection

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 API during execution, and can directly operate the internal properties and methods of any object.

Class C = Class forName("java.lang.String")

After loading the Class, an object of Class type is generated in the method area of heap memory (a Class has only one Class object), which contains the complete structure information of the Class. 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 Class, so we call it reflection

Research and application of Java reflection mechanism

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 runtime
  • 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:

  • Has an impact on performance. Using reflection is basically an interpretive 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.

Reflection related API s

  • java.lang.Class: represents a class
  • java.lang.reflect.Method: represents the method of the class
  • java.reflect.Field: represents the member variable of the class
  • java.lang.reflect.Constructor: the constructor that represents the class
  • ...
package kuangshen.reflection;

public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //Get the Class object of the Class through reflection
        Class c1 = Class.forName("kuangshen.reflection.User");
        System.out.println(c1);//class kuangshen.reflection.User

        //Conclusion: a Class has only one Class object in memory
        //After a Class is loaded, the whole structure of the Class will be encapsulated in the Class object
        Class c2 = Class.forName("kuangshen.reflection.User");
        Class c3 = Class.forName("kuangshen.reflection.User");
        Class c4 = Class.forName("kuangshen.reflection.User");
        System.out.println("c1"+c1.hashCode());//c121685669
        System.out.println("c2"+c2.hashCode());//c121685669
        System.out.println("c3"+c3.hashCode());//..
        System.out.println("c4"+c4.hashCode());//..
    }
}

//pojo class
class User{
    private int id;
    private String name;
    private int age;

    public User() {
    }

    public User(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 "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Class class

The following methods are defined in the Object class, which will be inherited by all subclasses

public final Class getClass()

The type of the return value of the above method is a Class class, which is the source of Java reflection. In fact, the so-called reflection is also well understood from the running results of the program,

That is, the name of the class can be obtained through object reflection.

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 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 will only have one Class instance in the JVM
A class object corresponds to one 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 calss class

Method nameFunction description
static ClassforName(String name)Returns the Class object with the specified Class name
Object newInstance()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 Class object
Class getSuperClass()Returns the Class object of the parent Class of the current Class 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[] fetDeclaredFields()Returns an array of Field objects

Get an instance of Class

How to create class

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

Class clazz = Person.class;

b) If the instance of a Class is known, call the getClass() method of the instance to get the Class object

Class clazz = person.getClass();

c) The full Class name of a Class is known, and the Class is in the Class path, which can be obtained through the static method forName() of Class

ClassNotFoundException may be thrown

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

d) The built-in basic data type can use the class name directly Type

e) We can use ClassLoader to explain later

package kuangshen.reflection;
//Test how the class is created
public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("This person is:"+person.name);//This person is: student

        //Method 1: obtained by object
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());//21685669
        //Method 2: get ClassForName
        Class  c2 = Class.forName("kuangshen.reflection.Student");
        System.out.println(c2.hashCode());//21685669

        //Pass the class name class
        Class c3 = Student.class;
        System.out.println(c3.hashCode());//21685669

        //Method 4: packing classes of basic built-in types have a Type attribute
        Class<Integer> c4 = Integer.TYPE;
        System.out.println(c4);//int

        //Get parent type
        Class c5 = c1.getSuperclass();
        System.out.println(c5);//class kuangshen.reflection.Person
        
    }
}
class Person{
    public String name;

    public Person() {
    }

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

class Student extends Person{
    public Student(){
        this.name = "student";
    }
}

class Teacher extends Person{
    public Teacher(){
        this.name = "teacher";
    }
}
There is a type of Class object
  • 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
import java.lang.annotation.ElementType;

//All types of class es
public class Test03 {
    public static void main(String[] args) {
        Class c1 = Object.class;//Class java lang.Object
        Class c2 = Comparable.class;//Interface java lang.Comparable
        Class c3 = String[].class;//One dimensional array class [Ljava.lang.String;
        Class c4 = int[][].class;//Two dimensional array class [[I]
        Class c5 = Override.class;//Annotation interface java lang.Override
        Class c6 = ElementType.class;//Enumerate class java lang.annotation. ElementType
        Class c7 = Integer.class;//Basic data type: class java lang.Integer
        Class c8 = void.class;//void           void
        Class c9 = Class.class;//Class itself is class java lang.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);

        //Only the element type is the same as the dimension, that is, the same class
        int[] a = new int[10];
        int[] b = new int[100];
        System.out.println(a.getClass().hashCode());//21685669
        System.out.println(b.getClass().hashCode());//21685669

    }
}
Java Memory Analysis

Class loading and ClassLoader

Class loading process

When a program actively uses a class, if the class has not been loaded into memory, the system will initialize the class through the following three steps.

Understanding of class loading and ClassLoader
  • 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. XML 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:
    • * * constructor method * *. The class constructor < clinit > () method is generated by the combination of the assignment actions of all class variables in the class and the statements in the static code block. (the class constructor is the constructor that constructs class information, not the constructor that constructs the class object.).
    • When initializing a class, if you find that its parent class has not been initialized, you need 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.
When does class initialization occur
  • Active reference of class (class initialization is bound to 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
    //When will the test class initialize
    public class Test06 {
    
        static {
            System.out.println("Main Be loaded");
        }
    
        public static void main(String[] args) throws Exception {
            //1. Active quotation
            //Son son = new Son();
            // Reflection also produces active references
            Class.forName("com.kuang.reflection.Son");
            
            
        }
    }
    
    class Father{
        static int b = 2;
        static {
            System.out.println("Parent class 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 the class that actually declares the domain will be initialized. For example, when a static variable of the parent class is referenced through a subclass, the subclass will not be initialized

      ///No initialization of subclasses:
      //Referencing a static variable of a parent class through a subclass will not cause subclass initialization**
      System.out.println(Son.b);
      
      Operation results:
      main Class is loaded
       The parent class is initialized
      2
      
    • Defining a class reference through an array does not trigger the initialization of this class

      //2. The array defines a class reference and will not trigger the initialization of this class
      Son[] arr  = new Son[5];
      
      Operation results:
      main Class is loaded
      
    • Reference constants do not trigger the initialization of this class (constants are stored in the constant pool of the calling class in the link phase)

      //3. Constant reference will not trigger the initialization of this class
      System.out.println(Son.M);
      
      Operation results:
      main Class is loaded
      1   
      
Role of class loader
  • The 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, 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 be dimensioned
    Keep loading (caching) for a period of time. However, the JVM garbage collection mechanism can recycle these Class objects

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

Class loader

public class Test05 {
  public static void main(String[] args) throws ClassNotFoundException {
      //Gets the class loader of the system
      ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
      System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2

      //Gets the parent class loader -- > extension class loader of the system loader
      ClassLoader parent = systemClassLoader.getParent();
      System.out.println(parent);//sun.misc.Launcher$ExtClassLoader@14ae5a5

      //Get the parent class loader of the extension class loader -- > the root loader (written in C/C + +) cannot be obtained
      ClassLoader parent1 = parent.getParent();
      System.out.println(parent1);//null

      //Test which class loader loads the current class
      ClassLoader classLoader = Class.forName("kuangshen.reflection.Test05").getClassLoader();
      System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2

      //Test who loaded the JDK internal class -- > is loaded by the root loader, so it cannot be printed
      ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
      System.out.println(classLoader1);//null

      //Gets the path where the system class loader can load
      System.out.println(System.getProperty("java.class.path"));
      /**
C:\Environment\jdk1.8.0_131\jre\lib\charsets.jar;
C:\Environment\jdk1.8.0_131\jre\lib\deploy.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\dnsns.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\jaccess.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\localedata.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\nashorn.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\sunec.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;
C:\Environment\jdk1.8.0_131\jre\lib\ext\zipfs.jar;
C:\Environment\jdk1.8.0_131\jre\lib\javaws.jar;
C:\Environment\jdk1.8.0_131\jre\lib\jce.jar;
C:\Environment\jdk1.8.0_131\jre\lib\jfr.jar;
C:\Environment\jdk1.8.0_131\jre\lib\jfxswt.jar;
C:\Environment\jdk1.8.0_131\jre\lib\jsse.jar;
C:\Environment\jdk1.8.0_131\jre\lib\management-agent.jar;
C:\Environment\jdk1.8.0_131\jre\lib\plugin.jar;
C:\Environment\jdk1.8.0_131\jre\lib\resources.jar;
C:\Environment\jdk1.8.0_131\jre\lib\rt.jar;
C:\Users\17316\IdeaProjects\test\out\production\test;
C:\Users\17316\IdeaProjects\test\src\Java\BingFaYuDuoXianChen\lib\commons-io-2.6.jar;
C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.1\lib\idea_rt.jar
      */
  }
}

Gets the complete structure of 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

  • ......
//Get class information

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

/**
 * class User{
 *     private int id;
 *     private String name;
 *     private int age;
 *     }
 */
public class Test06 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("kuangshen.reflection.User");

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

        //1. Get class name -- > get package name + class name
        System.out.println(c1.getName());//kuangshen.reflection.User

        //2. Get the simple name of the class -- > get the class name
        System.out.println(c1.getSimpleName());//User

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

        //3.2 be able to find all attributes
        Field[] fields1 = c1.getDeclaredFields();
        for (Field field: fields1) {
            System.out.println(field);
        }
        /**
         * private int kuangshen.reflection.User.id
         * private java.lang.String kuangshen.reflection.User.name
         * private int kuangshen.reflection.User.age
         */

        //3.3. Obtain the specified attribute
        Field name = c1.getDeclaredField("name");
        System.out.println(name);//private java.lang.String kuangshen.reflection.User.name

        //4. 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("c1.getMethods():"+method);
        }
        Method[] methods1 = c1.getDeclaredMethods();//Get all methods of this class
        for (Method method : methods1) {
            System.out.println("c1.getDeclaredMethods():"+method);
        }
        //Get the specified method overload, so add parameters
        Method getName = c1.getMethod("getName", null);
        System.out.println(getName);//public java.lang.String kuangshen.reflection.User.getName()
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(setName);//public void kuangshen.reflection.User.setName(java.lang.String)

        //5. Gets the specified constructor
        System.out.println("=================================");
        Constructor[] constructors = c1.getConstructors();//Get public
        for (Constructor constructor : constructors) {
            System.out.println("c1.getConstructors():"+constructor);
        }
        Constructor[] constructors1 = c1.getDeclaredConstructors();//Get all constructors
        for (Constructor constructor : constructors1) {
            System.out.println("c1.getDeclaredConstructors():"+constructor);
        }

        //Gets the specified constructor
        Constructor declaredConstructor = c1.getDeclaredConstructor(int.class, String.class, int.class);
        System.out.println("Gets the specified constructor"+declaredConstructor);//Gets the specified constructor public kuangshen reflection. User(int,java.lang.String,int)
    }
}

Summary:

1. Get class name - > get package name + class name

  • c1.getName() //kuangshen.reflection.User

2. Get the simple name of the class – > get the class name

  • c1.getSimpleName() //User

3. Get the properties of the class

  • 3.1 get public attribute

    • c1.getFields() / / only public attributes can be found
  • 3.2 be able to find all attributes

    • c1.getDeclaredFields()
  • 3.3. Obtain the specified attribute

    • c1.getDeclaredField("name");

4. Method to get class

  • c1.getMethods();// Get all public methods of this class and its parent class

  • c1.getDeclaredMethods();// Get all methods of this class

  • c1.getMethod(“getName”, null); // Get the specified method overload, so add parameters

5. Gets the specified constructor

  • c1.getConstructors(); // Get public

  • c1.getDeclaredConstructors(); // Get all constructors

  • c1.getDeclaredConstructor(int.class, String.class, int.class);

Create an object of a runtime class

What can you do with a Class object?

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

reflection? 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 completed through the Method class.
    • ① Get a Method object through the getMethod(String name,Clas... parameterTypes) Method of Class class and set the parameter type required for the operation of this Method.
    • ② 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 a static method, the formal parameter 9bject gbj can be null at this time
    • 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 this 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 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.
    • So that 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
  • Code test:

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    //Dynamic creation of information through reflection
    public class Test07 {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
            //Get Class object
            Class c1 = Class.forName("kuangshen.reflection.User");
    
            //1. Create object:
            //1.1 construct an object through newInstance()
            User user1 = (User) c1.newInstance();//It is essentially a parameterless construction of the call
            System.out.println(user1);//User{id=0, name='null', age=0}
    
            //1.2 create by constructor
            Constructor constructor = c1.getDeclaredConstructor(int.class, String.class, int.class);
            User user2 = (User) constructor.newInstance(001, "Lisa", 11);
            System.out.println(user2);//User{id=1, name='Lisa', age=11}
    
            //2. Call normal methods through reflection
            System.out.println("=============================================");
            //Create an object
            User user3 = (User) c1.newInstance();
            //Get a method by reflection
            Method setName = c1.getDeclaredMethod("setName", String.class);
            //invoke: activate and wake up
            //Parameter (object, "value of method")
            setName.invoke(user3,"China");
            System.out.println(user3.getName());//China
    
            //3. Operation properties by reflection
            System.out.println("=============================================");
            User user4 = (User) c1.newInstance();
            Field name = c1.getDeclaredField("name");
    
            //We can't directly operate private properties. We need to turn off the security monitoring of the program through: name setAccessible(true);
            name.setAccessible(true);
            name.set(user4,"Li Si");
            System.out.println(user4.getName());//Li Si
            /**
             * Class kuangshen.reflection.Test07 can not access a member of class kuangshen.reflection.User with modifiers "private"
             */
    
    
        }
    }
    

    Performance test:

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    //Test performance
    public class Test08 {
        public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
            test01();
            test02();
            test03();
    
        }
        //Ordinary method call
        public static void test01(){
            User user = new User();
            long start_time = System.currentTimeMillis();
            for (int i = 0; i < 1000000000; i++) {
                user.getName();
    
            }
            long end_time = System.currentTimeMillis();
            System.out.println("To execute 1 billion times in the ordinary way, it needs:"+(end_time-start_time)+"ms");
        }
    
        //Reflection mode call
        public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            User user = new User();
            Class c1 = user.getClass();
            Method getName = c1.getMethod("getName", null);
            getName.invoke(user,null);
            long start_time = System.currentTimeMillis();
            for (int i = 0; i < 1000000000; i++) {
                user.getName();
    
            }
            long end_time = System.currentTimeMillis();
            System.out.println("Reflection mode calls need to be executed 1 billion times:"+(end_time-start_time)+"ms");
        }
    
    
        //Call in reflection mode and turn off safety monitoring
        public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            User user = new User();
            Class c1 = user.getClass();
            Method getName = c1.getMethod("getName", null);
            getName.setAccessible(true);
            getName.invoke(user,null);
            long start_time = System.currentTimeMillis();
            for (int i = 0; i < 1000000000; i++) {
                user.getName();
    
            }
            long end_time = System.currentTimeMillis();
            System.out.println("Call in reflection mode, close the security monitoring call, and execute 1 billion times. It needs:"+(end_time-start_time)+"ms");
        }
    
    }
    

Get generic information

  • Java uses the mechanism of generic erasure to introduce generics. Generics in Java are only used by the compiler javac to ensure the security of data and avoid the problem of 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 has added ParameterizedType, GenericArrayType, TypeVariable and WildcardType to represent types that cannot be classified into Class but have the same name as the original type

  • ParameterizedType: indicates 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

//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 Exception {
        Method method = Test11.class.getMethod("test01", Map.class, List.class);
        //getGenericParameterTypes(): get the parameter type of the generic type
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType:genericParameterTypes) {
            System.out.println("#" + genericParameterType);
              // Judge whether genericParameterType is equal to ParameterizedType (structured parameter type)
            if (genericParameterType instanceof ParameterizedType){
                //Gettypearguments(): get real information
                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);
            }
        }
    }
}

Get annotation information

  • getAnnotations()
  • getAnnotation()
import java.lang.annotation.*;
import java.lang.reflect.Field;

//Practice reflection operation annotation
public class test12 {
    public static void main(String[] args) throws Exception {
        Class c1 = Class.forName("com.kuang.reflection.Studen2");
        //Get annotations through reflection
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation: annotations) {
            System.out.println(annotation);
        }

        //Gets the value of the annotated value
        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("age");
        Fieldkuang annotation = f.getAnnotation(Fieldkuang.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }

}

@Tablekuang("DB_student")
class Studen2{
    @Fieldkuang(columnName = "db_id",type = "int",length = 10)
    private int id;
    @Fieldkuang(columnName = "db_age",type = "int",length = 10)
    private int age;
    @Fieldkuang(columnName = "db_name",type = "int",length = 10)
    private String name;

    public Studen2() {
    }

    public Studen2(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 "Studen2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

//Annotation of class name
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)//Retention: indicates where our annotation is valid
@interface Tablekuang{
    String value();
}


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

}
Exercise: ORM

Object relationship Mapping

Keywords: Java

Added by homerjay on Thu, 03 Mar 2022 15:20:22 +0200