Annotation and reflection learning

Annotation and reflection

annotation

What is annotation?

Annotation is a new technology introduced from JDL 5.0

  • Not the program itself, you can explain the program (this is no different from the comment)
  • Can be read by other programs (such as compiler)
  • Annotations exist in the code as "@ annotation name". You can also add parameter values, such as @ SuppressWarning(value = "unchecked")
  • It can be attached to package, class, method, field, etc. to add additional auxiliary information
  • You can programmatically access these metadata through the reflection mechanism
    .

Built in annotation

  • @Override: defined in java.lang.Override. This annotation is used as a rhetorical device to indicate that one method declaration overrides another method declaration in the superclass
  • @Deprecated: defined in java.lang.Deprecated. This annotation can be used to modify classes, methods, attributes, and indicates that programmers are not supported to use this element, usually because it is dangerous or there is a better choice
  • @Suppresswarning: defined in java.lang.supplewarning to suppress warning messages generated during compilation. This annotation requires adding parameters
    • SupressWarning("all")
    • SupressWarning("unchekced")
    • SupressWarning({"unchecked", "deprecation"})
      .

Meta annotation
Function: responsible for annotating other annotations

  • @Target() is used to describe the scope of use of annotations, such as classes and methods
  • @Retention() indicates the level at which the annotation information needs to be saved. It is used to describe the annotation life cycle, generally in Runtime
  • @Document() indicates that the annotation will be included in the javadoc
  • @Inherited() indicates that the subclass can inherit the annotation in the parent class

.

Custom annotation

  • When using @ interface to customize annotations, it automatically inherits the java.lang.annotation.Annotation interface
  • @Interface is used to declare an annotation. Format: public @interface annotation name {definition content}
//Custom annotation
//String value(); Generally, when there is only one parameter, use value to pass the parameter. You don't need value = and use "" directly
public class Demo01 {
    //Annotations can display assignment. If there is no default value, we must assign default "" to the annotation
    @MyAnnotation(name = "JAVA",schools = "Tsinghua University")//If the parameter is defined, an error will be reported if the parameter is not written
    public void test(){

    }
}

@Target({ElementType.TYPE,ElementType.METHOD})//Can work with classes and methods
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    //Annotated parameters: parameter type + parameter name ();
    String name() default "";
    int age() default 0;
    int id() default -1;//If the default value is - 1, it means that it does not exist

    String[] schools() default {"Western open source","Tsinghua University"};
}

.
.

reflex

Reflection overview

  • ==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 the Reflection API during execution, and can directly operate the internal properties and methods of any object, or even operate private properties!
Class c1=Class.forName("Java.lang.String")
  • After the Class is loaded, a Class object will be 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, so we vividly call it reflection

Normal method: you need to introduce the "package class" name > > > instantiate through the new method > > > get the instantiated object

Reflection method: instantiate the object > > > getclass() > > > to get the complete "package class" name

For example, chestnuts:

//What is 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("com.kuang.reflection.User");
        System.out.println(c1);

        //Normal mode
        User user = new User();
        user.setAge(20);
        user.setId(001);
        user.setName("zhangsan");
        System.out.println(user.toString());

        Class c2 = Class.forName("com.kuang.reflection.User");
        Class c3 = Class.forName("com.kuang.reflection.User");
        Class c4 = Class.forName("com.kuang.reflection.User");

        //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
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());

    }

}

//Entity class: pojo,entity
class User{
    private String name;
    private int id;
    private int age;

    public User() {//Nonparametric structure
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        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;
    }

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

.
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
  • Call the member variables and methods of any object at run time
  • Get generic information at run time
  • Processing annotations at run time
  • Generate dynamic proxy
    .

Class class

Class is very important for reflection. The information obtained by an object after reflection: the properties, methods and constructors of a class, which interfaces a class implements and which classes it inherits. For each class, JRE reserves an object of constant class type. A class object contains information about a specific structure (class, interface, enum, annotation, p'p rimitive type, void, [])

  • Class itself is 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 file loaded into the JVM
  • All loaded structures in a Class can be completely obtained through Class
  • Class is the root of Reflection. For any class you want to load and run dynamically, you have to obtain the corresponding class object first

.
Common methods of Class:

Several methods to get Class:

  • Class c1 = A.class´╝Ť
  • Class c2 = a.getClass();
  • Classs c3 = Class.forName("xxx.xx.A");
  • Class c4 = Integer.TYPE of base type;
  • Obtained through ClassLoader
//What are the creation methods of test Class
public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("This person is:"+person.name);

        //Method 1: obtain the Class object through the object [if the instance of a Class is known, call the getClass() method of the instance to obtain the Class object]
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());

        //Method 2: forname obtain [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 an exception ClassNotFoundException may be thrown]
        Class c2 = Class.forName("com.kuang.reflection.Student");
        System.out.println(c2.hashCode());

        //Method 3: obtain through the class name. Class [the specific class is known and obtained through the class attribute of the class. This method is the most safe and reliable and has the highest program performance]
        Class c3 = Student.class;
        System.out.println(c3.hashCode());

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

        //Get parent type
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }
}

class Person{
    public String name;

    public Person() {//Nonparametric structure
    }

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

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

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

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

.

Which types can have Class objects?

//All types of class es
public class Test03 {
    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 = int[][].class;//Two dimensional array
        Class c5 = Override.class;//annotation
        Class c6 = ElementType.class;//enumeration
        Class c7 = Integer.class;//Basic data 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 is the same as the dimension, it is the same Class
        int[] a = new int[10];
        int[] b = new int[100];
        System.out.println(a.getClass().hashCode());//22307196
        System.out.println(b.getClass().hashCode());//22307196
    }
}

.

Java Memory Analysis

Java Memory

  • Heap:

    • new objects and arrays
    • It can be shared by all threads without storing other object references
      .
  • Stack:

    • Store the basic variable type (including the specific value of this basic type)

    • The variable of the reference object (the specific address of the reference in the heap will be stored)

  • Method area:

    • Can be shared by all threads
    • Contains all class and static variables

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.

  • Class loading: read the class file of the class into memory and create a java.lang.Class object for it. This process is completed by the class loader
  • Class Link: merge the binary data of the class into the JRE
  • Class initialization: the JVM is responsible for initializing the class

Take a chestnut

public class Test04 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.m);

        /*
        1.When loaded into memory, a Class object corresponding to the Class will be generated
        2.Link, m = 0 after link
        3.initialization
              <clinit>(){
                          System.out.println("A Class static code block initialization "");
                          m = 300;
                          m = 100;
              }

              m = 100
         */
    }
}

class A{
    static {
        System.out.println("A Class static code block initialization");
        m = 300;
    }

    /*
    m = 300
    m = 100
     */

    static int m = 100;

    public A(){
        System.out.println("A Class");
    }
}

Output results:
A Class static code block initialization
A Class
100

.

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
    • Use the methods of the java.lang.reflect package to make reflection calls to the class
    • When initializing a class, if its parent class is not initialized, the parent class will be initialized first
      .
  • Passive reference of class (class initialization will not occur)
    • When accessing a static code block, only the class that really lives in the code block 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 calling class in the link phase)

.
.

Role of class loader

  • The function of class loading: load the class file into memory, convert these static data into the runtime data structure of the method area, and then generate a java.lang.Class object representing this class in the heap as the access entry to the class data in the method area
  • Class caching: the standard JavaSE 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, and the JVM garbage collection mechanism can recycle these class objects

There are three types of loaders:

  1. System loader: the user-defined class loader you wrote is also the loader we use most. The parent loader is an extension loader and can get a reference
 //Gets the loader of the system class
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);//
  1. Extension loader: the loader of the classes in the jar package stored in the jre/lib/ext directory. The parent loader is the root loader and can get references
//Gets the parent class loader -- > extension class loader of the system class loader
ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);//
  1. Root loader: written in C + +, it is the class loader of the JVM. It is responsible for the JAVA platform core library and is used to load the core class library. The loader cannot be obtained directly and is null
//Get the parent class loader -- > root loader of the extension class loader (C/C + +)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);//null
//Class loader
public class Test06 {
    public static void main(String[] args) throws ClassNotFoundException {

        //Gets the loader of the system class
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@b4aac2

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

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

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

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

        //How to get the path that the system class loader can load
        System.out.println(System.getProperty("java.class.path"));

        //Parental delegation mechanism
        
    }
}

.

Gets the structure of the class runtime

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

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

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

        Field[] fields2 = c1.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field);
        }

        //Gets the value of the specified property
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

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

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

        //Gets the specified method
        //heavy load
        Method getName = c1.getMethod("getName",null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        //Gets the specified constructor
        System.out.println("==========================");
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("getDeclaredMethods:"+constructor);
        }

        //Gets the specified constructor
        Constructor constructor3 = c1.getConstructor(String.class, int.class, int.class);
        System.out.println("appoint:"+constructor3);
    }
}

.

Create objects by reflection
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 permissions
//Dynamically create objects through reflection
public class Test08 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //Get Class object
        Class c1 = Class.forName("com.kuang.reflection.User");

        //Construct an object
        User user = (User)c1.newInstance();//The essence is to call the parameterless constructor of the class
        System.out.println(user);

        //Creating objects through constructors
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User)constructor.newInstance("Qin Jiang",001,20);
        System.out.println(user2);


        //Call normal methods through reflection
        User user3 = (User)c1.newInstance();
        //Get a method by reflection

        //invoke: Activate
        //(object, "value of method")
        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.invoke(user3,"Mad God");
        System.out.println(user3.getName());//Mad God


        //Operation properties by reflection
        System.out.println("==============================");
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");

        //Private attributes cannot be annotated. We need to turn off the security detection of the program, and setAccessible(true) of attributes or methods;
        name.setAccessible(true);//Can pass. The private modified variable has a security protection mechanism
        name.set(user4,"Mad god 2");
        System.out.println(user4.getName());


    }
}

Call the specified method

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

  1. Obtain 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. Use Object invoke (Object obj,Object []) to call and pass the parameter information of the ovj object to be set to the method
  • If the return value of the Object object method or the original method has no return value, the run result returns null
  • If the original method is static, the formal parameter Object can be null
  • If the original method parameter list is empty, Object[] args is null
  • If the original method is declared private private, you need to call the setAccessible(true) of the method object before invoke(), so that you can make a violent reflection.

.
==About setAccessible(): = = its function is to start and disable the security check switch. When the Boolean value is true, the java program cancels the access check. When false, the access check is started.

  • Method, Field and Constructor objects all have setAccessible() methods
  • It improves the efficiency of reflection. If reflection must be used in the code, and the sentence code needs to be called frequently, please set it to true
  • So that private members that cannot be accessed can also be accessed

.

Performance comparison and analysis

//Analyze performance issues
public class Test09 {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        test01();
        test02();
        test03();
    }

    //Normal method call
    public static void  test01(){
        User user = new User();

        long startTime = System.currentTimeMillis();

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

        long endTime = System.currentTimeMillis();

        System.out.println("1 billion times with common methods:"+(endTime-startTime)+"ms");
    }

    //Reflection mode call
    public static void  test02() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        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("1 billion times in reflection mode:"+(endTime-startTime)+"ms");
    }

    //Reflection mode call off detection
    public static void  test03() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        User user = new User();
        Class c1 = user.getClass();

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

        long startTime = System.currentTimeMillis();

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

        long endTime = System.currentTimeMillis();

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

}

.

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 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: 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
//Get generics through reflection
public class Test10 {
    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Test10.class.getMethod("test01", Map.class, List.class);

        Type[] genericParameterTypes = method.getGenericParameterTypes();

        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("#"+genericParameterType);
            if (genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType)genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }

    }

    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;
    }
}
Output results:
#java.util.Map<java.lang.String, com.kuang.reflection.User>
class java.lang.String
class com.kuang.reflection.User
#java.util.List<com.kuang.reflection.User>
class com.kuang.reflection.User

.

Reflection operation annotation

//Practice reflection operation annotation
public class Test11 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.kuang.reflection.Student2");

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

        //Gets the value of the annotated value
        TableRuan tableRuan = (TableRuan)c1.getAnnotation(TableRuan.class);
        String value = tableRuan.value();
        System.out.println(value);

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


    }
}

@TableRuan("db_student")
class Student2{

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

    public Student2() {
    }

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

    public int getId() {
        return id;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

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

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

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

Tags: network mvc

Posted on Mon, 22 Nov 2021 13:25:34 -0500 by WebbieDave