Annotation and reflection

Posted by sergio-pro on Wed, 19 Jan 2022 04:23:12 +0100

What is annotation

Annoation: function

  • It is not the procedure itself, which can be explained
  • It can be read by other programs (such as compiler)
    Format: @ comment name can also add some parameter values, for example: (@ supplesswarning (value = "unchecked"))

Scope of use:
It can be attached to package, class, method, field, etc., which is equivalent to adding additional auxiliary information to them. We can access these metadata through reflection mechanism.

Built in annotation

  • @0verride overridden comments
  • @Deprecated is not recommended for programmers, but it can be used in a better way
  • @Supplerswarning suppression warning (with parameters)
public class Test01 extends Object{
    //Rewritten annotation
    @Override
    public String toString() {
        return super.toString();
    }
    @Deprecated
    public static void test(){
        System.out.println("Deprecated");
    }
    @SuppressWarnings("all")//Suppression warning
    public void test02(){
        List list = new ArrayList();
    }
    public static void main(String[] args) {
        test();

    }
}

Meta annotation

The function of meta annotation is to annotate other annotations. java defines four standard meta annotation types, which are used to describe other annotation types;
These types and the classes they support are in Java You can find (@ Target, @ Retention, @ Documented, @ Inherited) in lang.annotation package

  • @Target: used to describe the applicable scope of the annotation
  • @Retention: identifies the level at which annotation information needs to be saved and used to describe the annotation life cycle
  •                             (source < class < **runtime**)               
    
  • @Document: note that the annotation will be included in the javadoc
  • @Inherited: indicates that the subclass can inherit the annotation in the parent class

Custom annotation:

//Test meta annotation
@MyAnnoation
public class Test02 {

}
// Target identifies the scope of the annotation
//Define an annotation method to use on the class
@Target(value= {ElementType.METHOD,ElementType.TYPE})

//Identifies the level at which the annotation is valid
// source < class < runtime
@Retention(value = RetentionPolicy.RUNTIME)
//Indicates whether our annotation is generated in javadoc
@Documented
//Annotation that identifies whether the subclass inherits from the parent class
@Inherited
@interface MyAnnoation{

}

Custom annotation

Keyword: @ interface
When you use @ interface to customize annotations, you automatically inherit Java lang.annotation. Annotataion interface

analysis:

  • Format: public @interface annotation name {definition content}
  • Each of these methods actually declares an Oh ah parameter
  • The name of the method is the name of the parameter
  • The return value type is the type of the parameter
  • You can set the default value of the parameter through default
  • If there is only one parameter, you can use value (generally used)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//Custom annotation
public class Test03 {
    @MyAnnotation2(name = "hua",school = "Chongqing Yitong College")
    @MyAnnotatiaon3("hua")
    public void tets(){}
}



@Target(value={ElementType.METHOD,ElementType.ANNOTATION_TYPE})
@Retention(value= RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    //Annotated parameters: parameter type + parameter name ()
    String name() default "";
    int age() default 18 ;
    int id() default -1;//If the default value is - 1, it means that it does not exist. indexof returns - 1 if it cannot be found

    String[]  school() default "Chongqing Yitong College";
}
@Target(value={ElementType.METHOD,ElementType.ANNOTATION_TYPE})
@Retention(value= RetentionPolicy.RUNTIME)
@interface MyAnnotatiaon3{
    //Only value can be omitted
    String value();
}

Static VS dynamic language

Dynamic language is a kind of language that can change its structure at runtime: for example, new functions, objects and even code can be introduced, existing functions can be deleted or other structural changes.
Main dynamic languages: Object-C, c#, JavaScript, php, Python, etc

function f(){
    var x = "var a=3;var b=5;alert(a+b)";
    eval(x);//Change the value of x
}

Static language: that is, a language with immutable runtime structure. Such as java and c++
However, java can become a "quasi dynamic language" because of its reflection mechanism

Reflection overview

java Reflection

Reflection is the key to java being regarded as a dynamic language. The reflection mechanism allows programs to obtain any unknown internal information with the help of Reflection API during execution, and can directly operate the internal properties and methods of any object.

    Class c = Class.forName("String");

    public Test02() throws ClassNotFoundException {
    }

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), and this object contains complete Class structure information. We can see the structure of the Class through this formation. The object is like a mirror through which you can see the structure of the Class.

  • Normal method: import the required "package class" name = "" instantiate through new = "" to obtain the object
  • Reflection method: instantiate object = > getClass() method = > get the completed "package class" name

Functions provided by 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
  • . . . . Call the member variables and methods of any object
  • . . . . Processing annotations
  • . . . . Generate dynamic proxy

Advantages and disadvantages of reflection:

  • Advantages: realize dynamic creation and compilation, reflecting great flexibility
  • Disadvantages: it has a great impact on performance. Reflection is basically an interpretation operation that tells the JVM that we want it to meet our requirements. Such operations are always slower than performing the same operation directly.

Main API:

  • java.lang.Class stands for class
  • java.lang.reflect.Method
  • java.lang.reflect.Field
  • java.lang.reflect.Constructor

Class class


##Get an instance of Class

  • Class c = Person.class; Given the specific class, this method is the most safe and reliable and the program performance is the highest when obtained through the class attribute
  • Class c = person.getClass(); If a specific class is known, call the getClass () method of the modified instance to obtain the class object
  • Class c = Class.forName(“demo01.Student”); If the full name of the class is known, and the class path is obtained through the static method forname(), ClassNotFoundException may be thrown
package com.hua.reflection;
//What are the ways to create the test class
public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student("student");
        System.out.println("This person is:"+person);

        //Method 1: obtained by object
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
        //Method 2: forName
        Class c2 = Class.forName("com.hua.reflection.Student");
        System.out.println(c2.hashCode());
        //Method 3: get by class name
        Class c3 = Student.class;
        System.out.println(c3);
        //Method 4: packing classes of basic built-in types have a TYPE attribute
        Class c4 = Integer.TYPE;
        System.out.println(c4);
        //Method 5: get the type of parent class
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }
}
class Person{
    public String name;
    public Person() {
    }
    public Person(String name){
        this.name=name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
class Student extends Person{
    public Student(String name){
        this.name=name;
    }

    public Student() {

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

What objects does class have

package com.hua.reflection;

import java.lang.annotation.ElementType;

public class Test03 {
    public static void main(String[] args) {
        Class c1 = Object.class;
        Class c2 = Comparable.class;  //Interface
        Class c3 = String[].class;
        Class c4 = int[][].class;
        Class c5 = Override.class;
        Class c6 = ElementType.class;
        Class c7 = Integer.class;
        Class c8 = void.class; //Empty class
        Class c9 = 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());
        System.out.println(b.getClass());
    }
}

Class load memory analysis

Class initialization

package com.hua.reflection;
//When will the test class initialize
public class Test05 {
    static {
        System.out.println("Main Class is loaded");
    }
    public static void main(String[] args) throws ClassNotFoundException {
        // Active reference
        //Son son = new Son();//Main class = parent class = child class
        //Reflection also produces active references
        //Class.forName("com.hua.reflection.Son");//Main class = parent class = child class

        //A method that does not generate a reference to a class
        System.out.println(Son.b);
        Son[] array =new Son[5];// Array of classes
        System.out.println(Son.M);//Constant in constant pool
    }
}
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");
    }
    static int a = 100;
    static  final int M=1;
}

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. Net file representing this class in the heap Lang. class object, as the access entry of class data in the method area.

Class caching: the standard Java se class loader can find classes as required. Once a class is loaded into the class loader, it will be loaded (cached) for a period of time. The jvm garbage collection mechanism can recycle these class objects.

package com.hua.reflection;

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

        //Gets the parent class loader -- > extension class loader of the system class loader
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        //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 test06 = Class.forName("com.hua.reflection.Test06").getClassLoader();
        System.out.println(test06);
        //Test who loaded the classes built into the jdk
        test06 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(test06);//null

        //Get the path where the system class loader can load
        System.out.println(System.getProperty("java.class.path"));

        //Parent delegation mechanism: the packages (jar s and classes) created by yourself are found up first. If they are not available, they cannot be used
    }
}

Gets the runtime structure of the class

package com.hua.reflection;

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

//Get class information
public class Test07 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c = Class.forName("com.hua.reflection.user");
        //Gets the name of the class
        System.out.println(c.getName());// Get package name + class name
        System.out.println(c.getSimpleName());// Get class name

        user u = new user();
        System.out.println(u.getClass().getSimpleName());

        for (Field field : c.getDeclaredFields()) {//Get all attribute values of c, filed []
            System.out.println(field);
        }
        System.out.println("====================================================");
        //Gets the value of the specified property
        System.out.println(c.getDeclaredField("name"));//filed
        System.out.println("====================================================");
        //Method to get class
        for (Method method : c.getDeclaredMethods()) {
            System.out.println(method);
        }
        System.out.println("====================================================");
        //Gets the specified method
        System.out.println(c.getDeclaredMethod("getName",null));
        System.out.println(c.getDeclaredMethod("setName", String.class));

        //Gets the specified constructor
        Constructor[] constructor =c.getConstructors();
        for (Constructor constructor1 : constructor) {
            System.out.println(constructor1);
        }
        //Gets the specified constructor
        System.out.println(c.getConstructor(int.class,String.class,int.class));
    }
}

Dynamically create object execution methods

Create the object of the class through the newInstance () method

package com.hua.reflection;

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

//Create objects dynamically through reflection
public class Test08 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class c = Class.forName("com.hua.reflection.user");//Get class object
        System.out.println(c);
        //Construct an object
        user user = (user)c.newInstance();//Essentially calls the class's parameterless constructor
        System.out.println(user);

        //Creating objects through constructors
        Constructor constructor = c.getDeclaredConstructor(int.class,String.class,int.class);
        user user1 = (user)constructor.newInstance(001,"hua",10);
        System.out.println(user1);

        //Get a method by reflection
        Method method = c.getDeclaredMethod("setName", String.class);
        //invoke: the meaning of activation (object, value)
        method.invoke(user,"Hua");
        //user.setAge(10);
        //System.out.println(user.getAge()); // You can call it directly with an object
        System.out.println(user.getName());
        //Operation properties by reflection
        Field f = c.getDeclaredField("name");
        //We can't directly operate private properties. We need to turn off program security monitoring
        f.setAccessible(true);//Turn off security monitoring and setAccessible() of property or method
        f.set(user,"hua");
        System.out.println(user.getName());
    }
}

Performance analysis (setAccess)

package com.hua.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.attribute.UserDefinedFileAttributeView;

//Performance analysis problems
public class Test09 {
    //Normal mode call
    public static void test01(){
        User user = new User();
        user.setName("hua");
        long starttime = System.currentTimeMillis();//start time
        for (int i = 0; i < 100000000; i++) {
            user.getName();
        }
        long endtime = System.currentTimeMillis();//End time
        System.out.println("Ordinary call 1 billion times getName()"+(endtime-starttime)+"ms");
    }
    //Reflection mode call
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        User user = new User();
        Class c = user.getClass();
        Method method = c.getMethod("setName", String.class);
        method.invoke(user,"hua");
        long starttime = System.currentTimeMillis();//start time
        for (int i = 0; i < 100000000; i++) {
            user.getName();
        }
        long endtime = System.currentTimeMillis();//End time
        System.out.println("Reflection calls 1 billion times getName()"+(endtime-starttime)+"ms");
    }

    //Reflection mode call off detection
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        User user = new User();
        Class c = user.getClass();
        Method method = c.getMethod("setName", String.class);
        method.setAccessible(true);
        method.invoke(user,"hua");
        long starttime = System.currentTimeMillis();//start time
        for (int i = 0; i < 100000000; i++) {
            user.getName();
        }
        long endtime = System.currentTimeMillis();//End time
        System.out.println("Reflection call (close detection) 1 billion times getName()"+(endtime-starttime)+"ms");
    }

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


}

Reflection operation generics

package com.hua.reflection;

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

//Get generics through reflection
public class Test10 {
    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 NoSuchMethodException {
        Method method01 = Test10.class.getMethod("test01", Map.class, List.class);
        Type[] method01GenericParameterTypes = method01.getGenericParameterTypes();
        for (Type method01GenericParameterType : method01GenericParameterTypes) {
            System.out.println(method01GenericParameterType);
            if (method01GenericParameterType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) method01GenericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }
        System.out.println("sssssssssssssssssssssssssssssssssssssss");
        Method method02 = Test10.class.getMethod("test02", null);
        Type genericReturnType = method02.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    }
}

Get annotation information

package com.hua.reflection;

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

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

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

        //Get the value of annotation value
        MyAnnoation02 myAnnoation02 = (MyAnnoation02)c.getAnnotation(MyAnnoation02.class);
        String value = myAnnoation02.value();
        System.out.println(value);
        //Gets the annotation specified by the class
        Field name = c.getDeclaredField("name");
        Filed filed = name.getAnnotation(Filed.class);
        System.out.println(filed.columnNmae());
        System.out.println(filed.type());
        System.out.println(filed.length());
    }

}
@MyAnnoation02("db_student")
class Student2{
    @Filed(columnNmae = "db_id",type = "int",length = 10)
    private  int id;
    @Filed(columnNmae = "db_age",type = "int",length = 10)
    private int age;
    @Filed(columnNmae = "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;
    }
}

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

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

Topics: Java