JAVA Foundation_ Annotation and reflection

annotation

Basic notes:

**JAVA annotation: * * also known as JAVA annotation, is an annotation mechanism introduced by JDK 5.0. Not the program itself, the program can be revealed and can be read by other programs.

Format: @ + comment name (some can also add parameters)

**@Override 😗* rewrite. If it is found that its parent class or the referenced interface does not have this method, a compilation error will be reported.

    // @Override override annotation
    @Override
    public String toString() {
        return super.toString();
    }

**@Deprecated: * * mark obsolete method. If this method is used, a compilation warning will be reported.

 // @Deprecated is not recommended for programmers, but it can be used, or there is a better way
    @Deprecated
    public static void test(){
        System.out.println("Deprecated");
    }

@SuppressWarnings: instructs the compiler to ignore the warnings declared in the comments. Parameters are required.

    // @SuppressWarnings suppression warnings
    @SuppressWarnings("all")
    public void test02(){
        List list = new ArrayList<>();
    }

Meta annotation:

Meta annotation: responsible for annotating other annotations

@Target: describes the scope of use of annotations

**@Retention: * * describes the lifecycle of the annotation

**@Documented: * * this annotation will be included in the javadoc

**@Inherited: * * the subclass can inherit the annotation in the parent class

import java.lang.annotation.*;

// Test meta annotation
public class test02 {
    @MyAnnotation
    public void test(){
        
    }
}

// Define an annotation
// @Target indicates where our annotation can be used
@Target(value = {ElementType.METHOD,ElementType.TYPE})

// Retention indicates where our annotation is still valid
// If not, the default is class
// runtime > class > sources
@Retention(value = RetentionPolicy.RUNTIME)

// Documented indicates whether our annotations are generated in javadoc
@Documented

// The Inherited subclass can inherit the annotation of the parent class
@Inherited

// To define annotations, @ interface is required
@interface MyAnnotation{

}

Custom annotation

Using @ interface to customize annotations automatically inherits Java lang.annotation. Annotation interface

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 {
    // Annotations can display assignments. If there is no default value, annotations must be assigned without order
    @MyAnnotation2(name = "aa",sc)
    public void test(){}
    
    @MyAnnotation3("")
    public void test2(){
        
    }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    // Annotated parameters: parameter type + parameter name ();
    String name();
//    String name() default "";   Add default value, no parameters can be added
    int age() default 0;
    int id() default -1; // If the default value is - 1, it means that it does not exist
    String[] schools() default {"aa","bb"};
}

@interface MyAnnotation3{
    String value();
    // If there is only one value, value is used by default, and assignment is not required
}

Annotation components:

In the composition of java Annotation, there are three very important trunk classes. namely:

Annotation.java

package java.lang.annotation;
public interface Annotation {

    boolean equals(Object obj);

    int hashCode();

    String toString();

    Class<? extends Annotation> annotationType();
}

ElementType.java

package java.lang.annotation;

public enum ElementType {
    TYPE,               /* Class, interface (including annotation type), or enumeration declaration  */

    FIELD,              /* Field declaration (including enumeration constants)  */

    METHOD,             /* Method declaration  */

    PARAMETER,          /* Parameter declaration  */

    CONSTRUCTOR,        /* Construction method declaration  */

    LOCAL_VARIABLE,     /* Local variable declaration  */

    ANNOTATION_TYPE,    /* Annotation type declaration  */

    PACKAGE             /* Package declaration  */
}

RetentionPolicy.java

package java.lang.annotation;
public enum RetentionPolicy {
    SOURCE,            /* Annotation The information only exists during the compiler processing, and there is no Annotation information after the compiler processing  */

    CLASS,             /* The compiler stores the Annotation in the corresponding of the class Class file. Default behavior  */

    RUNTIME            /* The compiler stores the Annotation in a class file and can be read in by the JVM */
}

Note more detailed description: https://www.runoob.com/w3cnote/java-annotation.html

reflex

Basic definition of class:

**Reflection: * * load the class and get the components of the class

Class:

  1. Class itself is also a class
  2. Class objects can only be created by the system
  3. A loaded Class has only one Class instance in the JVM
  4. A class object corresponds to a class loaded into the JVM Class file
  5. Each Class instance will remember which Class instance it was generated from
  6. All loaded structures in a Class can be completely obtained through Class
  7. Class is the root of Reflection. For any dynamically loaded and running class, you should first obtain the corresponding class object
        // Get the class object of the class through reflection
        Class c1 = Class.forName("User");
        System.out.println(c1);

        Class c2 = Class.forName("User");
        Class c3 = Class.forName("User");
        
//        A class has only one class object in memory
//        After a class is loaded, the whole construction of the class will be encapsulated in the class object
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());


Get class type instance:

  1. If a specific class is known, this method is the most reliable and the program performance is the highest through the class attribute of the class
  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
  3. If the instance of a Class is known, call the getClass() method of the instance to get the Class object
  4. The built - in basic data type can use the class name directly Type
  5. Using Class Loader
        // Method 1: obtained by object
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());

        // Method 2: forname
        Class c2 = Class.forName("Student");
        System.out.println(c2.hashCode());

        // Method 3: pass the class name Class get
        Class c3 = Student.class;
        System.out.println(c3.hashCode());

        // Method 4: wrapper classes of basic built-in types have a Type attribute
        Class c4 = Integer.TYPE;
        System.out.println(c4);

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

Class loading and ClassLoader:

  • Load: load the bytecode content of the class file into memory, convert these static data into the runtime data structure of the method, and then generate a Java. Java.xml file representing this class Lang.class object

  • Link: the process of merging the binary code of java classes into the running state of the JVM.

    • Verification: ensure that the loaded class information complies with the JVM specification and there are no security problems

    • Preparation: the stage of formally allocating memory for class variables and setting the default initial value of class variables. These memory will be allocated in the method area

    • Resolution: the process of replacing the symbolic reference (constant name) of the virtual machine constant pool with a direct reference (address)

  • initialization:

    • The process of executing a class constructor () method.
    • When initializing a class, if it is found that its parent class has not been initialized, you need to touch the initialization of its parent class first
    • Virtual chance ensures that the () methods of a class are locked and synchronized correctly in a multithreaded environment.
// When does the test class initialize
public class Test06 {
    static {
        System.out.println("Main Class is loaded");
    }

    public static void main(String[] args) {
        // 1. Active quotation
        // Son son = new Son();
        // Reflection also produces active references
        try {
            Class.forName("Son");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
class Father{
    static {
        System.out.println("The parent class is loaded");
    }
}

class Son extends Father{
    static {
        System.out.println("Subclass loaded");
        m = 300;
    }
    static int m = 100;
    static final int M = 1;
}

When will class initialization occur?

Active reference of class (class initialization must occur)

  • When the virtual machine starts, initialize the class where the main method is located first
  • new is an object of a class
  • Call static members (except final constants) and static methods of the class
  • Using Java The method of lang.reflect package makes reflection calls to the class
  • When initializing a class, if its parent class is not initialized, initialize its parent class first

Passive reference of class (class initialization will not occur)

  • When accessing a static domain, only the class that actually declares the domain will be initialized
  • Defining class references through arrays does not initiate class initialization
  • Reference constants do not initialize this class

**Function of class loader: * * load classes into memory. There are boot class loader, extension class loader and system class loader.

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

        // Gets the loader of the system class
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

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

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

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

        // Test who loaded the JDK built-in classes
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);

        // How to get the path that the system loader can load
        System.out.println(System.getProperty("java.class.path"));
        
        // Parental delegation mechanism
            // java.lang.String -->
    }
}

Application of reflection:

Get the complete structure of the runtime class:

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

public class Test08 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("User");

//        User user = new User();
//        c1 = user.getClass();

        // Get the name of the class
        System.out.println(c1.getName());  // Get package name + class name
        System.out.println(c1.getSimpleName()); // Get class name

        // Get the properties of the class
        System.out.println("+++++++++++++++++++++++++++++++");
        Field[] fields = c1.getFields();   // Only public properties can be found

        fields = c1.getDeclaredFields(); // Find all properties
        for(Field field: fields){
            System.out.println(field);
        }
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        // Method to get class
        System.out.println("+++++++++++++++++++++++++++++++++");
        Method[] methods = c1.getMethods(); // Get all public methods of this class and its parent class
        for(Method method: methods){
            System.out.println("natural:"+method);
        }
        methods = c1.getDeclaredMethods(); // Get all methods of this class
        for(Method method : methods){
            System.out.println("getDeclareMethods:"+method);
        }
        // Gets the specified method
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        // Gets the specified constructor
        System.out.println("+++++++++++++++++++++++++++");
        Constructor[] constructors = c1.getConstructors();
        for(Constructor constructor : constructors){
            System.out.println("#"+constructor);
        }
        constructors = c1.getDeclaredConstructors();
        for(Constructor constructor : constructors){
            System.out.println("#" + constructor);
        }
        // Gets the specified constructor
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println("appoint:"+declaredConstructor);
    }
}

Performance comparison:

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

// Analyze performance issues
public class Test10 {
    // Normal mode call
    public static void test01(){
        User user = new User();

        long startTime = System.currentTimeMillis();

        for(int i = 0; i < 1000000000;i++){
            user.getName();
        }
        long endTime = System.currentTimeMillis();

        System.out.println("1 billion times with common methods:"+(endTime-startTime)+"ms");
    }
    // Reflection mode call
    public static void test02() 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 < 1000000000;i++){
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();

        System.out.println("The reflection method is executed 1 billion times:"+(endTime-startTime)+"ms");
    }
    // Reflection mode call off detection
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();

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

        long startTime = System.currentTimeMillis();

        for(int i = 0; i < 1000000000;i++){
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();

        System.out.println("Close detection and execute 1 billion times:"+(endTime-startTime)+"ms");
    }

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

Get generics:

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 Test11 {
    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 method = Test11.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes =  method.getGenericParameterTypes();
        for (Type genericParameterType: genericParameterTypes){
            System.out.println("#" + genericParameterType);
            if(genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for(Type actualTypeArgument : actualTypeArguments){
                    System.out.println(actualTypeArgument);
                }
            }
        }

        method = Test11.class.getMethod("test02", null);
        Type genericReturnType =  method.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for(Type actualTypeArgument : actualTypeArguments){
                System.out.println(actualTypeArgument);
            }
        }
    }
}

Get annotation information:

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

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

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

        // Get the value of the annotation
        Tablekuang tablekuang = (Tablekuang)c1.getAnnotation(Tablekuang.class);
        String value = tablekuang.value();
        System.out.println(value);

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

    }
}
@Tablekuang("db_student")
class Student2{

    @Filekuang(columnName = "db_id", type = "int", length = 10)
    private int id;
    @Filekuang(columnName = "db_age", type = "int", length = 10)
    private int age;
    @Filekuang(columnName = "db_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 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 Tablekuang{
    String value();
}

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

According to the notes made by the Java annotation and reflection of the UP master madness of station B. Video address

Keywords: Java reflection

Added by webster08 on Sun, 23 Jan 2022 02:47:39 +0200