Annotation and reflection

Posted by solon on Mon, 18 Oct 2021 08:58:30 +0200

Annotation and reflection - Annotation

What is annotation

  • Explain a meaning to a computer
  • Can be read by other programs
//What is annotation?
public class dom1 extends Object{
    //Rewrite annotation
    @Override
    public String toString() {
        return super.toString();
    }
}
  • Format: @ comment name, and some parameter values can be added, such as @ comment name (value = "parameter")
  • Additional supporting information
  • Check and constraints

Built in annotation

  • @Override: override method
  • @Deprecated: not recommended, but can be used
  • @SuppressWarnings: suppress warnings. Parameters need to be added
import java.awt.*;
import java.security.AllPermission;

//What is annotation?
public class dom1 extends Object{
    //Rewrite annotation
    @Override
    public String toString() {
        return super.toString();
    }

    @Deprecated
    public static void text(){
        System.out.println("666");
    }

    @SuppressWarnings("all")
    public void test(){
        int xx;
        List list = new List();
    }

    public static void main(String[] args) {
        text();
    }
}

Meta annotation

  • Responsible for annotating other annotations, which is also gradual
    • @Target: describes the scope of application of the annotation
    • @Retention: describes the lifecycle of annotations: runtime > class > source
    • @Document: generate annotation in Doc
    • @Inherited: the subclass can inherit the annotation in the parent class
import java.lang.annotation.*;

//Test notes
public class dom02 {

    @MyAnnotation
    public void test(){}
}

//Define an annotation
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface MyAnnotation{}

Custom annotation

  • Automatically inherit the Annotation interface
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

//Custom annotation
public class dom3 {
    //Annotations can be assigned explicitly. If there is no default value, they must be assigned
    @Test(name = "aaa")
    public void test(){}

    @Test2("00")//Only one parameter is value, which can be omitted
    public void test2(){}
}

@Target({ElementType.METHOD})
@interface Test{
    //Annotated parameter: parameter type + parameter name () default value
    String name() default "";
    int age() default 18;
    int id() default -1;  //The default value is - 1, which means it does not exist
    String[] come() default {"010101","333"};
}

@Target({ElementType.METHOD})
@interface Test2{
   String value();
}

Reflection overview

  • Reflection mechanism: Reflection

  • Dynamic language: a language whose structure can be changed at run time

  • Static language: cannot be changed!

  • java is a static language, but reflection mechanism can give it the characteristics of dynamic language - "quasi dynamic language";

  • Reflection: seeing the structure of a class through a mirror

Normal method: import package class name - new instantiation - instantiate object

Reflection method: instantiate object - "getClass() method" - get package class name

function f(){
    var x = "var a = 3 ; var b = s; alert(a+b)";
    eval(x);
}

Get reflection object

  • Dynamic object creation and compilation, flexibility
  • Performance impact, slower than direct operations
//What is reflection
public class dom4 extends Object{
    public static void main(String[] args) throws ClassNotFoundException {
        //Get class object through reflection
        Class c1 = Class.forName("study1.User");
        System.out.println(c1);

        //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("study1.User");
        Class c3 = Class.forName("study1.User");
        Class c4 = Class.forName("study1.User");

        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());
    }
}

//Entity class
class User{
    private String name;
    private int id;

    public User(){
    }

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

    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;
    }

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

Several methods to get class

//Test the methods of creating class class
public class dom5 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println(person.name);

        //Obtained by object
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
        //forname get
        Class c2 = Class.forName("study1.Student");
        System.out.println(c2.hashCode());
        //class name. class
        Class c3 = Student.class;
        System.out.println(c3.hashCode());
        //Wrapper classes with basic built-in properties have Type properties
        Class c4 = Integer.TYPE;
        System.out.println(c4.hashCode());

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

    }
}

class Person{
    public String name;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

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

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

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

class objects of all types

package study1;

import java.lang.annotation.ElementType;

//All types of class es
public class dom6 {
    public static void main(String[] args) {
        Class c1 = Object.class; //class
        Class c2 = Comparable.class; //Interface
        Class c3 = String[].class; // 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);

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

    }
}

Class load memory analysis

  • Core idea: java Memory understanding: heap, stack, constant pool, method area
package study1;

public class dom7 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.a);
        /**
         *1.Load the class class into memory and generate a java. long. Class object
         * 2.Link: it will verify whether the class information complies with the JVM virtual machine specification, security issues, formally allocate memory (heap area) for class variables and set the initial value of class variables
         * 3.Initialization: execute the < client > () method of the class constructor. When new, the class object in the heap returns to the method area to automatically collect the assignment action of variables and the data in the static code block
         *          Statement and merge the code. The class constructor constructs all the information of the class, not the class object. The JVM ensures that the < client > () method of a class is locked and synchronized correctly in multithreading.
         *
         * */
    }
}

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

    static int a = 100;
    public A (){
        System.out.println("A Class parameterless construction initialization");
    }
}

Initialization of analysis class

//When will the test initialize
public class dom8 {

    static {
        System.out.println("Main Method is loaded");
    }
    public static void main(String[] args) throws ClassNotFoundException {
        //Active reference
        //Son son = new Son();
        //Reflection produces an active reference
        //Class.forName("study1.Son");

        //Class initialization will not occur
        //Calling a parent method through a subclass does not initialize the subclass
        //System.out.println(Son.b);
		//Array definition class reference
        //Son[] array = new Son[1];
		//Reference constant
        //System.out.println(Son.A);
    }
}

class Father{
    static int b = 2;

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

class Son extends Father{

    static {
        System.out.println("Subclass loaded");
        a = 300;
     }
    static int a = 100;
    static final int A = 1;//static const 
}

Class loader

public class dom9 {
    public static void main(String[] args) throws ClassNotFoundException {

   //Bottom up check if loaded
        //Get system class loader -- sun.misc.Launcher$AppClassLoader@xxx
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);
        //Get the parent class loader of the class loader - > extended class loader -- - sun.misc.Launcher$ExtClassLoader@
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);
        //Get the parent class of the extension class loader -- > boot loader (written in core! C + +, which the user cannot get directly) -- null
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

        //Test which loader the current class is
        ClassLoader classLoader = Class.forName("study1.dom9").getClassLoader();
        System.out.println(classLoader);

        //Test who loads the Jdk inner class
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);

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

        //Parent delegation mechanism -- multiple detection to detect package security and avoid duplicate package names

    }
}

Get class runtime structure

  • Attribute: Field
  • Method: method
  • Constructor: constructor
  • Interface: Interface
  • Annotation: Annotation
  • Superclass: inherited parent class
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//Get class information
public class dom10 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("study1.Son");

        System.out.println(c1.getName()); //Get package name and class name
        System.out.println(c1.getSimpleName());  //Get class name

        //Get the properties of the class
        Field[] fields = c1.getFields();//public property
        fields = c1.getDeclaredFields();//All properties
        for (Field field : fields) {
            System.out.println(field);
        }

        //Method to get class
        for (Method method : c1.getMethods()) {
            System.out.println(method);
        }

        //Gets the constructor of the class
        for (Constructor constructor : c1.getConstructors()) {
            System.out.println(constructor);
        }

        for (Constructor declaredConstructor : c1.getDeclaredConstructors()) {
            System.out.println(declaredConstructor);
        }
    }
}

Dynamically create object execution methods

  • Call the newInstance method of the Class object
  • setAccessible: security check, skip permission detection: method,Field,Constructor
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class dom11 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class c1 = Class.forName("study1.Son");

        Son o = (Son) c1.newInstance();
        System.out.println(o);

        //Create an object through a constructor -- call a parameterized constructor
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class,"");
        Son o1 = (Son) declaredConstructor.newInstance("");

        //Call normal methods through reflection
        Son o2 = (Son) c1.newInstance();
        Method declaredMethod = c1.getDeclaredMethod("",String.class);
        //Activation method
        declaredConstructor.invoke("object","Method value");

        //By reflecting the operation attributes, you cannot directly operate the attributes. You need to close the security check
        Son o3 = (Son)c1.newInstance();

    }
}

Performance comparison and analysis

  • Test results:

Common method: 32ms
Reflection method: 20677ms
Closing inspection: 779ms

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

//Analyze performance and execute 100 million times
public class dom12 {

    //Common method
    public static void test1() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            user.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Common method:" +(endTime-startTime)+"ms");
    }
    //Reflection call
    public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();

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

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            //Activation method: object name, parameter
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Reflection method:" +(endTime-startTime)+"ms");
    }

    //Close check
    public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();

        Method getName = c1.getDeclaredMethod("getName", null);
        //Close safety check
        getName.setAccessible(true);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            //Activation method: object name, parameter
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Close check:" +(endTime-startTime)+"ms");
    }

    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        test1();
        test2();
        test3();
    }
}

Get generic information*

//Get generic information through reflection
public class dom13 {

    public void test(Map<String,User>map, List<User>list){
        System.out.println("test");
    }

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

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

        for (Type genericParameterType : test.getGenericParameterTypes()) {
            System.out.println(genericParameterType);
            if(genericParameterType instanceof ParameterizedType){
                for (Type actualTypeArgument : ((ParameterizedType) genericParameterType).getActualTypeArguments()) {
                    System.out.println(actualTypeArgument);
                }
            }
        }
    }
}

Get annotation information

  • ORM - > Object Relational Mapping
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedType;

public class dom14 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("study1.Student2");

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

        //Get annotated value
        Table annotation = (Table)c1.getAnnotation(Table.class);
        String value = annotation.value();
        System.out.println(value);

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

@Table("student")
class Student2{
    @Field(col = "id",type = "int",length = 10)
    private int id;
    @Field(col = "age",type = "int",length = 10)
    private int age;
    @Field(col = "name",type = "varchar",length = 5)
    private String name;

    public Student2() {
    }

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

    public Student2(int age) {
        this.age = age;
    }

    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 Table{
    String value();
}

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

Topics: Java Spring