Annotation and reflection

Annotation and reflection

Comment: give people an explanation of the program so that people can better understand the program

Annotation: it can not only give people an explanation of the program, but also be recognized by the compiler and check the constraint code

Format of Annotation:

@Comment name (some special parameter values can be added)

Built in annotation

1,@override

This annotation is only used for rhetoric, indicating that one method declaration intends to override another method declaration in the superclass.

2,@Deprecated

Indicates that programmers are not encouraged to use such elements. Usually, it is dangerous or has a better choice, but it can still be used

3,@SuppressWarnings

Used to suppress compile time warnings

Meta annotation

Responsible for annotation of other annotations

@Target is used to describe the scope of use of annotations (class, method, constructor or what)

@Retention indicates the level at which the annotation information is saved. It is used to describe the annotation life cycle (source < class < runtime)

@Document indicates that the annotation will be included in the javadoc

@Inherited indicates that the child class can inherit the annotation from the parent class

Custom annotation

@Interface is used to customize annotation format: public @interface annotation name (define content)

Each of these methods actually declares a configuration parameter

The name of the method is the name of the parameter

The return value type is the parameter type (the return value can only be the 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

Annotation elements must have values. When defining annotation elements, we often use the empty string 0 as the default value

@MyAnnotation(schools="southeast")
public class Test1 {
    @MyAnnotation1("kk")
    @MyAnnotation(name="main",schools="southeast")
    public static void main(String[] args) {
        System.out.println("hello");

    }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    //Annotation parameter type parameter name ();
    //String name();
    String name() default "";//If there is a default value, you can not write the parameter
    int age() default 0;
    int id() default -1;//The default value is - 1, which means it does not exist. indexof returns - 1 if it cannot be found
    String[] schools();

}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation1{
    String value();//Only when the parameter name is defined as value, the above code can not write the parameter =, the default value
}

Dynamic language and static language

Dynamic language: a language whose structure can be changed at runtime (for example, new functions, objects and even code can be introduced, existing functions can be deleted or other structural changes). Generally speaking, it means that the code can change its structure according to some conditions at runtime

Main dynamic languages: Object-C, c#, Javascript, PHP, Python

Static language: as opposed to dynamic language, a language whose runtime structure cannot be changed becomes a static language

Main static languages: Java, C, C++

The Java language can achieve quasi dynamic performance through reflection mechanism

Reflection

During execution, the reflection runtime obtains the internal information of any class with the help of the Reflection API, and directly operates the internal properties and methods of any object

Advantages and disadvantages of reflection:

1. Advantages: it can dynamically create objects and compile, reflecting great flexibility

2. Disadvantages: since reflection is an explanatory language, its efficiency is lower than that of direct execution

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 a class

Reflection method

[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-ysnejs4m-1633065637510) (C: \ users \ 84054 \ appdata \ roaming \ typora user images \ image-20210925182642210. PNG)]

Get the method of Class

  1. If a specific class is known, it is obtained through the class attribute of the class. This method is the most safe and reliable, and the program performance is the highest.
System.out.println(User.class);
  1. If an instance of a Class is known, call the getClass () method of the instance to obtain the Class object

    User u1=new User("Mike",10,1);
    System.out.println(u1.getClass());
    
  2. If the full Class name of a Class is known and the Class is under the Class path, it can be obtained through the static method forName() of Class class, and classnotfoundexception may be thrown

Class c1=Class.forName("Annotation.User");
  1. The built-in basic data type can directly use the class name. Type
Class c4=Integer.TYPE;
System.out.println(c4);
  1. You can also use ClassLoader

Where types can have class es

Class c1=Class.class;         //Class can create class objects
Class c2=Comparable.class;    //interface can create class objects
Class c3= ElementType.class;  //Enum can create class objects
Class c4=String[].class;      //A unary array can create a class object
Class c5=int[][].class;       //Binary arrays can create class objects
Class c6=int.class;           //Basic data types can create class objects
Class c7=Override.class;      //Annotations can create class objects
Class c8=void.class;          //void can create a class object

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

The output result of the corresponding class above

class java.lang.Class
interface java.lang.Comparable
class java.lang.annotation.ElementType
class [Ljava.lang.String;
class [[I
int
interface java.lang.Override
void

Note: you can copy and paste multiple data with alert

Java memory map

The method area of Java stores the information of each class (including class name, method information and field information), static variables, constants and code compiled by the compiler; the heap data area is used to store objects and arrays (special objects);

[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-ckvj01r3-1633065637515) (C: \ users \ 84054 \ appdata \ roaming \ typora \ user images \ image-20210928223041107. PNG)]

As can be seen from the above figure, stack frames are stored in the Java stack, and each stack frame corresponds to a called method. The stack frame includes local variables, operand stack, and references to the runtime constant pool of the class to which the current method belongs (the concept of runtime constant pool is discussed in the method area) (Reference to runtime constant pool), method return address, and some additional information.

JAVA class loader

The function of class loader: load the bytecode content of class file into memory, convert these static data into the runtime data structure of method area, and then generate a java.lang.class object representing this class in the heap as the access interface of class data in method area

Acquisition of JAVA class loader

//Get system class loader
ClassLoader loader = ClassLoader.getSystemClassLoader();
System.out.println(loader);
//Get the parent class loader of the system class loader -- > platform class loader
ClassLoader parent = loader.getParent();
System.out.println(parent);
//Gets the root loader compiled by C/C + +
ClassLoader root = parent.getParent();
System.out.println(root);
//Get this class loader (this class is called Classload)
ClassLoader classLoader = ClassLoad.class.getClassLoader();
System.out.println(classLoader);
//Get the parent class loader of this class
ClassLoader parent1 = classLoader.getParent();
System.out.println(parent1);

The running results of the above code

jdk.internal.loader.ClassLoaders A p p C l a s s L o a d e r @ 2 f 0 e 140 b j d k . i n t e r n a l . l o a d e r . C l a s s L o a d e r s AppClassLoader@2f0e140b jdk.internal.loader.ClassLoaders AppClassLoader@2f0e140bjdk.internal.loader.ClassLoadersPlatformClassLoader@27d6c5e0
null
jdk.internal.loader.ClassLoaders A p p C l a s s L o a d e r @ 2 f 0 e 140 b j d k . i n t e r n a l . l o a d e r . C l a s s L o a d e r s AppClassLoader@2f0e140b jdk.internal.loader.ClassLoaders AppClassLoader@2f0e140bjdk.internal.loader.ClassLoadersPlatformClassLoader@27d6c5e0

Get reflection object

User u= new User();
//Gets the class of an object from an object
Class aClass = u.getClass();
System.out.println(aClass);

//Get the class according to the specific name of the class
Class aClass1 = Class.forName("Annotation.User");
System.out.println(aClass1);

//Get class from class
Class userClass = User.class;
System.out.println(userClass);

Acquisition of JAVA class methods and properties

 Class test = Class.forName("Annotation.User");//Get a class first
        //Get method of public type
        Method[] methods = test.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        //Get all types of methods
        Method[] methods1 = test.getDeclaredMethods();
        for (Method method : methods1) {
            System.out.println(method);
        }
        //Gets a specified method
        Method getName = test.getDeclaredMethod("getName",null);
        System.out.println(getName);


        //Get properties of public permission
        Field[] fields = test.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        //Get all types of properties, including private type
        Field[] fields1 = test.getDeclaredFields();
        for (Field field : fields1) {
            System.out.println(field);
        }
        //Gets a specified property
        Field id = test.getDeclaredField("id");
        System.out.println(id);

Creating objects with reflection classes

Create Class object: call newinstance() method of Class object

Two conditions are required to create an object using the above method:

  1. Class must have a parameterless constructor
  2. The constructor of the class needs sufficient access rights

How to create an object for a class without a parameterless constructor?

Creating objects through constructors

  1. Get the constructor of the formal parameter type specified by this Class through getdeclaraedconstructor (Class... parameterTypes) of Class class
  2. Pass an object array into the formal parameters of the constructor, which contains all the parameters required by the constructor
  3. Strengthen objects through Constructor
//Get class object
Class t = Class.forName("Annotation.User");
//Construct an object (create an object through a parameterless constructor)
User user =(User) t.newInstance();
System.out.println(user);
//Creating objects through constructors
Constructor constructor = t.getDeclaredConstructor(String.class, int.class, int.class);
User user1=(User) constructor.newInstance("Network security",18,1);
System.out.println(user1);
//Get a method through reflection
Method setName = t.getDeclaredMethod("setName", String.class);
setName.invoke(user1,"security");
System.out.println(user1);
System.out.println(user1.getName());
//Modify attributes through reflection
Field name = t.getDeclaredField("name");
//When private properties or methods cannot be operated directly, we can access them by setting their access permissions
//Set reflection permission to accessible type
name.setAccessible(true);
name.set(user1,"kkkkk");
System.out.println(user1);

The results of the above code execution

User{name='null', age=0, id=0}
User{name = 'network security', age=18, id=1}
User{name = 'safe', age=18, id=1}
security
User{name='kkkkk', age=18, id=1}

Note: the User class mentioned above is a pre created class with certain properties and methods, and its code is as follows

class User{
    private String name;
    private int age;
    private int id;

    public User() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public int getId() {
        return id;
    }

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

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

Performance analysis of objects created by various methods

static final long num=1000000000;
public static void test01(){
    User user=new User();
    long starttime=System.currentTimeMillis();
    for (int i = 0; i < num; i++) {
        user.getName();
    }
    long endtime=System.currentTimeMillis();
    System.out.println("Time spent creating normal object methods:"+(endtime-starttime)+"ms");

}
public static void test02() throws IllegalAccessException, InstantiationException {
    User user=new User();
    Class user1 = user.getClass();
    User u =(User) user1.newInstance();
    long starttime=System.currentTimeMillis();
    for (int i = 0; i < num; i++) {
        u.getName();
    }
    long endtime=System.currentTimeMillis();
    System.out.println("Time spent creating objects for reflection classes:"+(endtime-starttime)+"ms");

}
public static void test03() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    User user=new User();
    Class user2 = user.getClass();
    Method getName = user2.getDeclaredMethod("getName");

    long starttime=System.currentTimeMillis();
    for (int i = 0; i < num; i++) {
        getName.invoke(user, null);
    }
    long endtime=System.currentTimeMillis();
    System.out.println("Time spent creating object with security check reflection method call:"+(endtime-starttime)+"ms");

}

public static void test04() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    User user=new User();
    Class user2 = user.getClass();
    Method getName = user2.getDeclaredMethod("getName");
    getName.setAccessible(true);

    long starttime=System.currentTimeMillis();
    for (int i = 0; i < num; i++) {
        getName.invoke(user, null);
    }
    long endtime=System.currentTimeMillis();
    System.out.println("Time spent creating object without security check reflection method call:"+(endtime-starttime)+"ms");

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

}

Time spent creating normal object method: 914ms
Time taken for reflection class to create object: 749ms
Time spent creating object with security check reflection method call: 3591ms
Time spent creating object without security check reflection method call: 1633ms

How to use reflection to obtain specific information of annotations

public class ReflectAnnotation {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        //Get a class
        Class s = Class.forName("Annotation.Student");
        //Get the annotation of this class
        Annotation[] annotations = s.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //Get an object of class annotation
        name annotation = (name) s.getAnnotation(name.class);
        //Get the internal content of class annotation
        String value = annotation.value();
        System.out.println(value);
        
        //An object that gets the id attribute of the class
        Field id = s.getDeclaredField("id");
        //Get all annotation information under the object
        Annotation[] annotations1 = id.getAnnotations();
        for (Annotation annotation1 : annotations1) {
            System.out.println(annotation1);
        }
        //Get the specific information of an annotation under the id attribute object
        RefineField annotation1 =(RefineField) id.getAnnotation(RefineField.class);
        System.out.println(annotation1.column());
        System.out.println(annotation1.type());
        System.out.println(annotation1.length());

    }

}

@name("Student")
class Student{
    @RefineField(column = "id",type = "int",length = 10)
    private int id;
    @RefineField(column = "age",type = "int",length = 10)
    private int age;
    @RefineField(column = "name",type = "int",length = 10)
    private String name;

    public Student() {
    }

    public Student(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 "Student{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
//Define an annotation about the class
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface name{
    String value();
}
//Define an annotation about attributes
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface RefineField{
    String column();
    String type();
    int length();
}

The running answer of the above code

@Annotation.name("Student")
Student
@Annotation.RefineField(column="id", type="int", length=10)
id
int
10

   "id=" + id +
            ", age=" + age +
            ", name='" + name + '\'' +
            '}';
}

}
//Define an annotation about the class
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface name{
String value();
}
//Define an annotation about attributes
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface RefineField{
String column();
String type();
int length();
}

**The running answer of the above code**

@Annotation.name("Student")
Student
@Annotation.RefineField(column="id", type="int", length=10)
id
int
10

Keywords: Java Spring

Added by ishboo on Fri, 01 Oct 2021 07:35:37 +0300