Annotation + reflection reading

1, Annotation

1. Introduction

  • JDK1.5. The new technology introduced is not the program itself, but can explain the program (no difference from annotation)
  • Annotations can be read by other programs (such as compiler) (this is the biggest difference from annotations, which can be used as the processing flow of information processing)

2. 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 registration can be used for rhetorical devices, attributes and classes, which means that members are not encouraged to use such elements, usually because it is dangerous or there are better choices, but it can still be used, but it is not recommended

@SuppressWarnings

  • Defined in Java Lang. suppresswarnings, used to suppress warnings at compile time
parameterexplain
deprecationWarning that an obsolete class or method was used
uncheckedWarning when an unchecked transformation is performed, such as using a collection without specifying a generic type
fallthroughcase penetration occurs when a switch statement is
pathThere is a warning that the path does not exist in the classpath, source file path, etc
serialWarning when a serialVersionUID definition is missing on a serializable class
finallyWarning when any finally clause cannot be completed
allWarning about all of the above

In fact, the @ SuppressWarnings annotation is rarely used. Most people prefer to use the all parameter

2, Custom annotation

1. Use @ interface to customize annotations

Using its annotations automatically inherits Java lang.annotation. Annotation interface

2. Key points

2.1.@interface is used to declare an annotation

  • Format: public @interface annotation name (definition body)

2.2. Each method in its interface actually declares a configuration parameter

  • The name of the method is the name of the parameter
  • The return value type is the type of the parameter (the return value type 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

2.3. be careful

  • Annotation element must have value! When we define annotation elements, we often use empty string and 0 as the default value
  • Negative numbers (such as: - 1) are often used to indicate the meaning of nonexistence

3. Meta annotation

3.1 introduction

  • Meta annotations are used to annotate other annotations
  • Java defines four standard meta annotation types, which are used to provide descriptions of other annotation types

3.2 type

These types and the classes they support are in Java You can find the following in the lang.annotation package:

  1. @Target
    Function: used to describe the scope of application of the annotation (i.e. where the described annotation can be used)
Modified rangeValue ElementType
Package packagePACKAGE
Class, interface, enumeration, Annotation typeTYPE
Type member (method, constructor, member variable, enumeration value)CONSTRUCTOR: user description CONSTRUCTOR
FIELD: used to describe the FIELD
METHOD: used to describe the METHOD
Method parameters and local variablesLOCAL, VARIABLE:: used to describe LOCAL variables
METHOD: used to describe parameters
package java.lang.annotation;
@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();
}

  1. @Retention
Value RetentionPolicyeffect
SOURCEValid in source file (i.e. source file retention)
When Java files are compiled into class files, annotations are discarded
CLASSValid in class file (i.e. class reserved)
But the jvm was abandoned when it loaded the class file
RUNTIMEValid at run time (i.e. reserved at run time)
The annotations are not only saved in the class file, but also exist after the jvm loads the class file
The Runtime can be read by the reflection mechanism

These three life cycles correspond to: java source file (. java file) - > Class file - > bytecode in memory

First of all, the life cycle length SOURCE < CLASS < RUNTIME must be clear, so where the former can work, the latter must also work. Generally, if you need to dynamically obtain annotation information at RUNTIME, you can only use RUNTIME annotation; If you want to perform some preprocessing operations during compilation, such as generating some auxiliary code (such as ButterKnife), use the CLASS annotation; if you only do some checking operations, such as @ Override and @ SuppressWarnings, you can use the SOURCE annotation.

package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
  1. @Document
  2. @Inherited

3.3 realization

Annotation class:

package cn.edu.chan.test;

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

/**
 * @Author Cicada
 * @Date 2021/8/7 12:38
 */
@Target(value={ElementType.METHOD,ElementType.TYPE}) //It can be annotated on methods and classes
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest01 {

    String str() default "";  //If the initial value is not defined, the defined annotation needs to pass in the corresponding value, otherwise an error will be reported
    int integer1() default 0;
    int integer2() default -1;  //-1 means that this value does not exist
}

Implementation test class:

package cn.edu.chan.test;

/**
 * @Author Cicada
 * @Date 2021/8/7 13:10
 */
//@AnnotationTest01
public class Test01 {

    @AnnotationTest01(str = "11",integer1 = 0,integer2 = 1)
    public void test01(){

    }
}

3, Reflection read annotation

1. What is ORM (Object Relationship Mapping)

Abbreviation: Object Relational Mapping
For example:

  • Class corresponds to table structure
  • Attribute and field correspondence
  • Object and record correspondence

2. Use annotations to complete the mapping relationship between class and table structure

Annotation class of class:

package cn.edu.chan.annotation;

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

/**
 * @author Cicada
 * @version 1.0
 * @date 2021/8/8 10:08
 */
@Target(value={ElementType.TYPE}) //Can annotate to class
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest02 {
        String value();
}

Attribute annotation class:

package cn.edu.chan.annotation;

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

/**
 * @author Cicada
 * @version 1.0
 * @date 2021/8/8 10:13
 */
@Target(value={ElementType.FIELD}) //Can be annotated to attributes
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest03 {
    String columName();

    String type();

    int length();

}

Entity:

package cn.edu.chan.annotation;


/**
 * @author Cicada
 * @version 1.0
 * @date 2021/8/8 10:08
 */
@AnnotationTest02("user")
public class User {

    @AnnotationTest03(columName = "name", type = "varchar", length = 10)
    private String username;

    @AnnotationTest03(columName = "psw", type = "varchar", length = 15)
    private String password;

    @AnnotationTest03(columName = "age", type = "int", length = 3)
    private int age;

    public User() {
    }

    public User(String username, String password, int age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

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

Reflection test class:

package cn.edu.chan.annotation;

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

/**
 *Use reflection to read annotation information and simulate the process of processing annotation information
 * @author Cicada
 * @version 1.0
 * @date 2021/8/8 10:08
 */
public class Test02 {

    public static void main(String[] args) throws ClassNotFoundException {
        Class clazz = Class.forName("cn.edu.chan.annotation.User");

        //Get all annotations of the class
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

        //Gets the specified annotation of the class
        AnnotationTest02 annotation = (AnnotationTest02)clazz.getAnnotation(AnnotationTest02.class);
        System.out.println(annotation.value());

        //Get the annotation of the properties of the class
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            AnnotationTest03 annotationTest03 = field.getAnnotation(AnnotationTest03.class);
            System.out.println(annotationTest03.columName()+"___"+
                    annotationTest03.type()+"___"+annotationTest03.length());
        }

        //Annotation reflection obtains information such as table name, spell out SQL statements, and then execute relevant SQL to generate corresponding entity class tables in the database
    }
}

4, Reflection mechanism

1. General

Java reflection mechanism is to know all the properties and methods of any class in the running state; For any object, you can call any of its methods and properties; This kind of dynamically acquired information and the function of dynamically calling object methods are called the reflection mechanism of Java language.

  1. To dissect a Class, you must first obtain the bytecode file object of the Class, and the dissection uses the methods in the Class Therefore, first get the Class object corresponding to each bytecode file.
  2. Objects represent or encapsulate some data.
  3. After a Class is loaded, the JVM will create a Class object corresponding to the Class, and the whole structure information of the Class will be put into the corresponding Class object.
  4. This Class object is like a mirror, through which I can see all the information of the corresponding Class.

2. Acquisition of class object

Class object acquisition is not so big. Some of the main acquisition methods are those commonly used. Remember, such as class Methods such as forname (fully qualified class name) are sufficient

package cn.edu.chan.myclass;

/**
 * @author Cicada
 * @version 1.0
 * @date 2021/8/8 11:13
 */
public class Test01 {
    public static void main(String[] args) {
        String path = "cn.edu.chan.annotation.User";

        try {

            Class clazz = Class.forName(path);
            //Objects represent or encapsulate some data After a Class is loaded, the JVM will create a Class object corresponding to the Class
            // The entire structure information of the Class will be placed in the corresponding Class object.
            //This Class object is like a mirror, through which I can see all the information of the corresponding Class.
            System.out.println(clazz.hashCode());

            Class clazz2 = Class.forName(path); //A Class corresponds to only one Class object
            System.out.println(clazz2.hashCode());

            Class strClazz = String.class;
            Class strClazz2 = path.getClass();
            System.out.println(strClazz==strClazz2);

            Class intClazz =int.class;

            int[] arr01 = new int[10];
            int[][] arr02 = new int[30][3];
            int[] arr03 = new int[30];
            double[] arr04 = new double[10];

            System.out.println(arr01.getClass().hashCode());
            System.out.println(arr02.getClass().hashCode());
            System.out.println(arr03.getClass().hashCode());
            System.out.println(arr04.getClass().hashCode());


        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

result:

1163157884
1163157884
true
1956725890
356573597
1956725890
1735600054

Process finished with exit code 0

It is also clear that a Class corresponds to only one Clss object, but the Class objects corresponding to different dimensions are different.

3. Apply the reflection API to obtain class information (class name, attribute, method, constructor, etc.)

package cn.edu.chan.myConstructor;

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

/**
 * Apply the reflection API to obtain class information (class name, property, method, constructor, etc.)
 *
 * @author Cicada
 * @version 1.0
 * @date 2021/8/8 23:47
 */
public class Test01 {
    public static void main(String[] args) {
        String path = "cn.edu.chan.annotation.User";

        try {
            Class clazz = Class.forName(path);

            //Gets the name of the class
            System.out.println(clazz.getName());    //Get package name + class name: CN edu. chan. annotation. User
            System.out.println(clazz.getSimpleName());  //Obtained class name: User

            //Get attribute information
            //   Field[] fields = clazz.getFields(); // Only public fields can be obtained
            Field[] fields = clazz.getDeclaredFields(); //Get all field s
            Field f = clazz.getDeclaredField("username");
            System.out.println(fields.length);
            for (Field temp : fields) {
                System.out.println("Properties:" + temp);
            }
            //Get method information
            Method[] methods = clazz.getDeclaredMethods();
            Method m01 = clazz.getDeclaredMethod("getUsername", null);
            //If the method has parameters, the class object corresponding to the parameter type must be passed
            Method m02 = clazz.getDeclaredMethod("setUsername", String.class);
            for (Method m : methods) {
                System.out.println("method:" + m);
            }

            //Get constructor information
            Constructor[] constructors = clazz.getDeclaredConstructors();
            Constructor c = clazz.getDeclaredConstructor(String.class, String.class, int.class);
            System.out.println("Get constructor:" + c);
            for (Constructor temp : constructors) {
                System.out.println("Constructor:" + temp);
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

result:

**cn.edu.chan.annotation.User
User
3
 Properties: private java.lang.String cn.edu.chan.annotation.User.username
 Properties: private java.lang.String cn.edu.chan.annotation.User.password
 Properties: private int cn.edu.chan.annotation.User.age
 method: public java.lang.String cn.edu.chan.annotation.User.toString()
method: public void cn.edu.chan.annotation.User.setUsername(java.lang.String)
method: public java.lang.String cn.edu.chan.annotation.User.getUsername()
method: public int cn.edu.chan.annotation.User.getAge()
method: public void cn.edu.chan.annotation.User.setPassword(java.lang.String)
method: public void cn.edu.chan.annotation.User.setAge(int)
method: public java.lang.String cn.edu.chan.annotation.User.getPassword()
Get constructor: public cn.edu.chan.annotation.User(java.lang.String,java.lang.String,int)
Constructor: public cn.edu.chan.annotation.User()
Constructor: public cn.edu.chan.annotation.User(java.lang.String,java.lang.String,int)**

4. Dynamic operations through reflection API: constructor, method and attribute

package cn.edu.chan.myConstructor;

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

/**
 * Apply the reflection API to obtain class information (class name, property, method, constructor, etc.)
 *
 * @author Cicada
 * @version 1.0
 * @date 2021/8/8 23:47
 */
public class Test01 {
    public static void main(String[] args) {
        String path = "cn.edu.chan.annotation.User";

        try {
            Class clazz = Class.forName(path);

            //Gets the name of the class
            System.out.println(clazz.getName());    //Get package name + class name: CN edu. chan. annotation. User
            System.out.println(clazz.getSimpleName());  //Obtained class name: User

            //Get attribute information
            //   Field[] fields = clazz.getFields(); // Only public fields can be obtained
            Field[] fields = clazz.getDeclaredFields(); //Get all field s
            Field f = clazz.getDeclaredField("username");
            System.out.println(fields.length);
            for (Field temp : fields) {
                System.out.println("Properties:" + temp);
            }
            //Get method information
            Method[] methods = clazz.getDeclaredMethods();
            Method m01 = clazz.getDeclaredMethod("getUsername", null);
            //If the method has parameters, the class object corresponding to the parameter type must be passed
            Method m02 = clazz.getDeclaredMethod("setUsername", String.class);
            for (Method m : methods) {
                System.out.println("method:" + m);
            }

            //Get constructor information
            Constructor[] constructors = clazz.getDeclaredConstructors();
            Constructor c = clazz.getDeclaredConstructor(String.class, String.class, int.class);
            System.out.println("Get constructor:" + c);
            for (Constructor temp : constructors) {
                System.out.println("Constructor:" + temp);
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

result:

User{username='null', password='null', age='0'}
Xiao Ming
 Xiao Wang
 Xiao Hong
 Xiao Hong

5. Get generic information through reflection

package cn.edu.chan.myConstructor;

import cn.edu.chan.annotation.User;

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

/**
 * Get generic information through reflection
 * @author Cicada
 * @version 1.0
 * @date 2021/8/9 10:03
 */
public class Test03 {
    public void test01(Map<String, User> map, List<User> list){
        System.out.println("Test03.test01()");
    }
    public Map<Integer,User> test02(){
        System.out.println("Test03.test02()");
        return null;
    }
    public static void main(String[] args) {
        try {
            //Gets generic information for the specified method parameter
            Method m = Test03.class.getMethod("test01", Map.class,List.class);
            //getGenericParameterTypes: returns - an array of type types whose method parameters are generic (parameterized type). Type []
            Type[] t = m.getGenericParameterTypes();
            for (Type paramType : t) {
                System.out.println("#"+paramType);
                //ParameterizedType is an interface that can be used to verify whether a generic type is parameterized
                if(paramType instanceof ParameterizedType){
                    //Gets the concrete type of the runtime generic
                    Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
                    for (Type genericType : genericTypes) {
                        System.out.println("Generic type:"+genericType);
                    }
                }
            }
            //Gets the generic information of the return value of the specified method
            Method m2 = Test03.class.getMethod("test02", null);
            //getGenericReturnType: Return - returns an array of type types whose value is generic (parameterized type). Type []
            Type returnType = m2.getGenericReturnType();
            //ParameterizedType is an interface that can be used to verify whether a generic type is parameterized
            System.out.println("###"+returnType);
            if(returnType instanceof ParameterizedType){
                //Gets the concrete type of the runtime generic
                Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
                for (Type genericType : genericTypes) {
                    System.out.println("Return value, generic type:"+genericType);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


result:

#java.util.Map<java.lang.String, cn.edu.chan.annotation.User>
Generic type: class java.lang.String
 Generic type: class cn.edu.chan.annotation.User
#java.util.List<cn.edu.chan.annotation.User>
Generic type: class cn.edu.chan.annotation.User
###java.util.Map<java.lang.Integer, cn.edu.chan.annotation.User>
Return value, generic type: class java.lang.Integer
 Return value, generic type: class cn.edu.chan.annotation.User

Type is the high-level public interface of all types and, of course, the parent Class of Class.
They include primitive types, parameterized types, array types, type variables, and primitive types.

Keywords: Java reflection

Added by lucasrd on Thu, 30 Dec 2021 14:42:46 +0200