Annotation and reflection

Annotation and reflection

annotation

Function: it can be read by other programs, not the program itself, and can explain the program.

You can also add comments by using the parameter name: @

Where Annotation is used: it is attached to package, class, method, field, etc., which is equivalent to adding additional auxiliary information. The access to these metadata can be realized through reflection mechanism programming.

Common built-in annotations

@Override: only applicable to modified methods, indicating that one method intends to override the declaration of another method in the superclass.

@Deprecated: used to modify methods, attributes and classes. It is not recommended for programmers, or there is a better way.

@SuppressWarnings: used to suppress compile time warnings.

  • suppreessWarnings("all"):
import java.util.ArrayList;
import java.util.List;

public class Test01 extends  Object {
    //override is an annotation that indicates the rewriting of a method
    @Override
    public String toString() {
        return super.toString();
    }
    @Deprecated //Programmers are not recommended to use, or better methods
    public static void test(){
        System.out.println("Deprecated");
    }
    @SuppressWarnings("all")//Suppression warning
    public  static void test2(){
        List list=new ArrayList();
    }

    //annotation
    public static void main(String[] args) {
            test();
            test2();
    }
}

Meta annotation

Responsible for annotation and other annotations (meta annotation of 4 standards)

@Target: used to describe the scope of use of annotations

@Retention: indicates the level at which annotations need to be saved. This annotation information is used to describe the lifecycle of annotations.

SOURCE < class < runtime

@Document: notes will be included in javadoc

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

Example: define a simple annotation

import java.lang.annotation.*;

import static java.lang.annotation.ElementType.*;

public class Test2 {
    @myannotation//Define your own annotation. Only @ annotation at the method can succeed
    public void test(){

    }
}
//Define an annotation. Target indicates where the annotation can be used
@Retention(RetentionPolicy.RUNTIME)//Valid only at runtime
@Target(value ={ElementType.METHOD,ElementType.TYPE})
@Documented//Indicates whether our annotation is generated in JAVADOC
    
@interface myannotation{

}

Custom annotation

(public) @ interface annotation name {definition content}

If the user-defined annotation is declared in a class, public needs to be removed

1. Each method actually declares a configuration parameter

2. The name of the method is the name of the parameter

3. The return value type is the type of parameter

4. You can declare the default value of the parameter through default

5. If there is only one parameter member, the general parameter name is value

6. There must be annotation elements. When defining annotation elements, we often use empty string, and 0 is the default value.

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

public class Test3 {
    /*
    Customize an annotation
     */
    //The annotation can display the assignment. If there is no default value, the annotation must be assigned
    @MyAnnotation(name="hello")
    public void test(){}
    @MyAnnotation1("hello+")
    public void test2(){}
}
//Defining an annotation can be defined on a class or a method
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)//Annotation lifecycle
@interface MyAnnotation{
    //Annotation parameter: parameter type + parameter name ()
  String name() default "";//The default value setting can be blank
    int age() default  0;
    int id() default -1;//The default value is - 1, which means it does not exist
    String[] schools() default {"hello","world"};

}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)//Annotation lifecycle
@interface MyAnnotation1{
    String value();
    
}

Reflection mechanism

Make java realize the function of 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 always generated in the method area of heap memory. This object contains the structure information of the complete Class. You can see the structure of the Class through this object.

  • Normal method: import the required package name - > instantiate through new - > obtain the instantiated object
  • Reflection method: instantiate object - > getClass () method - > get the complete package class name

Get reflection object

Main API s related to reflection:
java.lang.Class: represents a class

java.lang.reflect.method: represents the method of the class

java.lang.reflect.Field: represents the member variable of the class

java.lang.reflect.Constructor: represents the constructor of the class

Define in the Object Class: public final Class getClass(), the return type is Class, and the name of the Class can be obtained through Object reflection.

Class itself is also a class. Class objects can only be created by the system.

Class common methods

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-xtq2tuwx-1615889393504) (C: \ users \ Lenovo \ appdata \ roaming \ typora user images \ image-20210316094607792. PNG)]

Get an instance of Class

1. Given the specific class, this method is the safest and most reliable to obtain through the class attribute of the class

Class cla=Persson.class

2. If the instance of a Class is known, call the getClass() method of the instance to obtain the Class object

Class cla=Person.getClass();

3. The full Class name of a Class is known, and the Class is in the Class path. You can use the static method forName() of Class to get it

Class cla=Class. Forname (package name. Class name)

//What are the test Class acquisition methods
public class Test05 {
    public static void main(String[] args) {
        person person=new student();
        System.out.println("This man is"+person.name);
        //1. Obtained by object
        Class c1=person.getClass();
        System.out.println(c1.hashCode());
        //2. Obtained through forName
        try {
            Class c2=Class.forName("student");
            System.out.println(c2);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //3. Pass: class name class
        Class c3=student.class;
        System.out.println(c3);
        //4. The wrapper class of the basic built-in class has a TYPE attribute
        Class c4=Integer.TYPE;
        System.out.println(c4);
        //5. Get parent type
        Class c5=c1.getSuperclass();
        System.out.println(c5);
    }
}
class person{
    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(){
        this.name="hello";
    }
}
class teacher extends person{
    public teacher(){
        this.name="world";
    }

}
result:
This man is hello
class student
class student
class student
int
class person

What types can have class objects

ALT can copy multiple lines

import java.lang.annotation.ElementType;

//All types of class es
public class Test06 {
    public static void main(String[] args) {
Class c1=Object.class;
Class c2=Comparable.class;
Class c3=String[].class;
Class c4=int[][].class;
Class c5=Override.class;
Class c6=ElementType.class;
Class c7=Integer.class;
Class c8=void.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().hashCode());
        System.out.println(b.getClass().hashCode());
    }
}
result:
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
460141958
460141958

Class load memory analysis

Class loading (read the class file of the class into memory and create a java.lang.Class object for it, which is completed by the class loader)

->Class link (merge the binary data of the class into the JRE: formally allocate memory for the class variable (static) and set the default initial value of the variable, which will be allocated in the method area)

->Class initialization (the JVM is responsible for initializing the class: the process of executing the () method of the class constructor, and automatically collecting the assignment actions of all class variables and the statements in the static code block during compilation)

[the external chain image transfer fails. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-q8bwhjrl-1615889393510) (C: \ users \ Lenovo \ appdata \ roaming \ typora user images \ image-20210316150512052. PNG)]

public class Test07 {
    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.After the link is completed, m=0(0 is the default initial value of int type)
        3.Initialization, execute the < clinit > () method of the class constructor, and automatically collect the assignment actions of all class variables and the statements in the static code block during compilation,
        <clinit>{
         System.out.println("A Static code block initialization of class "");
          m=300;
          m=100;}
         */
    }
}
class A{
    static{
        System.out.println("A Class");
        m=300;
    }
    static int m=100;
    public A(){
        System.out.println("A Nonparametric construction of class");
    }
}

When does class initialization occur

1. Active reference of class

  • When the virtual machine starts, first initialize the class where the main() method is located

  • new is an object of a class

  • Call static members (except FINAL) and static methods of the class

  • Using Java The lang.reflect method makes a reflection call to the class

  • When initializing a class, if its parent class is not initialized, its parent class will be initialized first

    public class Test08 {
        /*
        When will the test class initialize
         */
        static{
            System.out.println("main Class is loaded");
        }
        public static void main(String[] args) {
            //1. Active quotation
            son son=new son();
            //2. Reflection also produces active references
            try {
                Class.forName("son");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    class father{
        static int b=2;
        static{
            System.out.println("The parent class is being loaded...");
        }
    }
    class son extends father{
        static{
            System.out.println("Subclass loaded");
        }
        static int m=100;
        static final int M=1;
    }
    result:
    main Class is loaded
     The parent class is being loaded...
    Subclass loaded
    

    Passive reference of class (class initialization will not occur)

    1. When accessing a static domain, the domain will be initialized only when it is actually declared. For example, when the static variable of the parent class is called through the subclass, the subclass will not be initialized.

    2. Defining class references through arrays will not trigger class initialization

    3. Reference constants will not trigger the initialization of this class (constants are stored in the constant pool of the calling class in the link phase)

  //Methods that do not generate references f to classes
        System.out.println(son.b);
 son[] aray=new son[3];
result: main Class is loaded
    The parent class is being loaded...
    2

Role of class loader

Load the bytecode content of the class file into the memory, convert these static data into the runtime data structure of the method area, and then generate the Java. Java of this class in the heap Lang. class object, as the access entry of class data in the method area.

public class Test09 {
    public static void main(String[] args) {
        //Get loader of system class
       ClassLoader c1= ClassLoader.getSystemClassLoader();
        System.out.println(c1);
        //Get the parent class loader - > extension class loader of the system class loader
        ClassLoader c2= ClassLoader.getSystemClassLoader().getParent();
        System.out.println(c2);
        //Root loader
        ClassLoader c3=c2.getParent();
        System.out.println(c3);
        //Test which loader loads the current class
        ClassLoader c4= null;
        try {
            c4 = Class.forName("Test09").getClassLoader();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(c4);
        //How to get the path that the system class loader can load
        System.out.println(System.getProperty("java.class.path"));
        //Parental delegation mechanism
        //java.lang.String->
/*
C:\Program Files\Java\jdk1.8.0_201\jre\lib\charsets.jar;
C:\Program Files\Java\jdk1.8.0_201\jre\lib\deploy.jar;
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\access-bridge-64.jar;
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\cldrdata.jar;
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\dnsns.jar;
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jaccess.jar;
.....
E:\Project\out\production\Annotation and reflection;
E:\IntelliJ IDEA 2018.1.6\lib\idea_rt.jar
 */
    }
}

Create an object of a runtime class

Example: get class information through reflection

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

//Get class information
public class Test10 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        User user=new User();
        Class s=user.getClass();
       //Get package name + class name
        System.out.println(s.getName());
        //Class name
        System.out.println(s.getSimpleName());
        //Get the properties of the class,
        System.out.println("----------");
        //getFields() can only find the public attribute
        Field[] field=s.getFields();
        for(Field field1:field){
            System.out.println(field1);
        }
        //All attributes can be obtained
        System.out.println("----------");
        Field[] fields=s.getDeclaredFields();
        for(Field field2:fields){
            System.out.println(field2);
        }
        //Gets the specified attribute
        Field f=s.getDeclaredField("name");
        System.out.println(f);
        //Methods of this class (and all methods of this class)
        System.out.println("natural------------");
        Method[] methods=s.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("=============");
        //Get all methods of this class (including private)
        Method[] Dmethods=s.getDeclaredMethods();
        for (Method dmethod : Dmethods) {
            System.out.println(dmethod);
        }
        //Get the specified method
        Method m=s.getMethod("getName");
        System.out.println(m);
        //Parameterized method
        Method m2=s.getMethod("setName", String.class);
        System.out.println(m2);
        //Gets the specified constructor
        Constructor[] constructors =s.getConstructors();
        Constructor[] constructors1=s.getDeclaredConstructors();
        System.out.println("Constructor obtained by common method");
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("whole====================");
        for (Constructor constructor : constructors1) {
            System.out.println(constructor);
        }
        //Gets the specified construction method
        Constructor con=s.getConstructor(String.class,int.class,int.class);
        System.out.println(con);
    }
}

Example: create objects dynamically through reflection

1. Call the newInstance() method of the class object

1) Class must have a parameterless constructor

2) Constructor access should be sufficient

    //Get Class object
       Class c= Class.forName("User");
       //To build an object is essentially to call the parameterless constructor of the class
       User user= (User) c.newInstance();
        System.out.println(user);

2. There is no parameterless constructor. You can instantiate only after explicitly calling the constructor in the class and passing in the parameters

① Get the constructor of the specified parameter type in this Class through getdeclaraedconstructor() of Class class

② Pass an object array to the constructor, which contains all the parameters required by the constructor

③ Instantiate objects through Constructor

 //Creating objects through constructors
        //Gets the specified construction method
        Constructor con=c.getConstructor(String.class,int.class,int.class);
       User user1= (User) con.newInstance("hello",1,2);
        System.out.println(user1);

Example: call the specified method attribute

1. Get getmethod() and set the parameter type required for this method operation

2. Use Object invoke(Object obj,object[] args) to call and pass the parameter information of the set obj object to the method.

Note: ① Object corresponds to the return value of the original method. If there is no return value, it is null

② If the original method is static, parameter 1 can be null

③ If the original method parameter list is empty, parameter 2 is null

④ If the original method is private, the method Field Constructor object explicitly called before invoking invoke has setacceptable (true) method: the switch to start and disable security check

 //Call normal methods through reflection
        User user2= (User) c.newInstance();
        //Get a method by reflection
       Method method= c.getMethod("setName", String.class);
       //Activate the execution method invoke (transfer object, parameter value)
        method.invoke(user2,"hello");
        System.out.println(user2.getName());
        //Private attributes cannot be manipulated directly through reflection
        User user3= (User) c.newInstance();
        Field name=c.getDeclaredField("name");
        //Turn off permission detection and use set for operation attributes
        name.setAccessible(true);
        name.set(user3,"world");
        System.out.println(user3.getName());

performance analysis

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

//Analyze performance issues
public class Test12 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test1();
        test2();
        test3();
    }
        //Normal mode call
        public static void test1(){
        User user = new User();
        long starttime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }
        long endtime = System.currentTimeMillis();
        System.out.println("It is necessary to execute 1 billion times in the ordinary way"+(endtime-starttime)+"ms");
    }
        //Reflection mode call
        public static void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            User user = new User();
           Class c=user.getClass();
            Method m=c.getMethod("getName",null);
            long starttime = System.currentTimeMillis();
            for (int i = 0; i < 1000000000; i++) {
                m.invoke(user,null);
            }
            long endtime = System.currentTimeMillis();
            System.out.println("Reflection mode needs to be executed 1 billion times"+(endtime-starttime)+"ms");
        }
        //Reflection mode call, turn off detection
        public static void test3() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            User user = new User();
            Class c=user.getClass();
            Method m=c.getMethod("getName",null);
            m.setAccessible(true);
            long starttime = System.currentTimeMillis();
            for (int i = 0; i < 1000000000; i++) {
                m.invoke(user,null);
            }
            long endtime = System.currentTimeMillis();
            System.out.println("Reflection mode, closed detection, need to execute 1 billion times"+(endtime-starttime)+"ms");
        }
}
Results: it takes 60 minutes to execute 1 billion times in the ordinary way ms
 It takes 6719 to execute 1 billion times in reflection mode ms
 Reflection mode, it takes 2345 to close the detection and execute 1 billion times ms

Get annotation information

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

//Practice reflection operation annotation
public class Test13 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
     Class c1= Class.forName("student2");
     //Get comments
     Annotation[] ann=c1.getAnnotations();
        for (Annotation annotation : ann) {
            System.out.println(annotation);
        }
        //Gets the value of the specified annotation
        Table annotation=(Table)c1.getAnnotation(Table.class);
        String value= annotation.value();
        System.out.println(value);
        //Gets the annotation specified by the class attribute
        Field f=c1.getDeclaredField("name");
        Fieldde s=f.getAnnotation(Fieldde.class);
        System.out.println(s.columnName());
        System.out.println(s.type());
        System.out.println(s.length());
    }
}
@Table("db_student")
class student2{
    @Fieldde(columnName = "id",type="int",length=10)
    private int id;
    @Fieldde(columnName = "age",type="int",length=10)
    private int age;
    @Fieldde(columnName = "name",type="varchar",length=3)
    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 int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

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

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

    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 Fieldde{
    String columnName();
    String type();
    int length();

}
result:@Table(value=db_student)
db_student
name
varchar
3      

Tags: reflection

Posted by burfo on Fri, 01 Apr 2022 22:26:50 +0300