Annotation and reflection

Keywords: Java

Annotation and reflection

annotation

What is annotation

  • Annotation is a new technology introduced in jdk1.5.
  • Function of Annotation:
    • Not the procedure itself, the procedure can be explained;
    • It can be read by other programs, such as compilers.
  • Format of Annotation
    • "@ annotation name" can also take parameters, for example: @SuppressWarnings(value="unchcked")
  • Where is Annotation used?
    • It can be attached to package, class, method and field, which is equivalent to adding additional auxiliary information to them. It can also access these metadata through reflection mechanism programming.

Built in annotation

  • @Override: defined in java. lang Override. This annotation is only applicable to rhetorical devices, indicating that one method declaration intends to override another method declaration in the superclass.
  • @Deprecated: defined in Java. lang. Deprecated. This annotation can be used for rhetoric, attributes, and classes to indicate that programmers are not encouraged to use such elements, usually because it is dangerous or there are better choices.
  • @SuppressWarnings: defined in Java. lang. SuppressWarnings to suppress warnings at compile time.
  • Different from the previous two comments, you need to add a parameter to use it correctly. These parameters have been defined. We can use them selectively.

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 can be found in the java. lang annotation package. (@Target,@Retention,@Documented,@Inherited)
    • @Target: used to describe the scope of use of annotations (that is, where the described annotations can be used).
    • @Retention: indicates the level at which the annotation information needs to be saved. It is 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.
import java.lang.annotation.*;

public class TestAnnotation {
    @MyAnnotion
    public void test(){
    }
}
// Define an annotation
/*
Target Where can annotations be used
ElementType.METHOD Valid on method ElementType.TYPE class
 */
@Target(value = ElementType.METHOD)
/*
@Retention Where does it work
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
@interface MyAnnotion{
}

Custom annotation

  • When using @ interface to customize annotations, it automatically inherits the java. lang annotation. Annotation interface.
  • analysis:
    • @Interface is used to declare an annotation. Format: public@ interface annotation name {definition 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 type of the parameter (the return value can only be the basic type, Class, String,enum)
    • You can declare the default value of the parameter through defau;
    • If there is only one parameter member, the general parameter name is vaue;
    • An annotation element must have a value. When defining an annotation element, we often use an empty string with 0 as 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 TestCustomAnnotation {
    // Annotations can display assignment. If there is no default value, the annotation must be assigned
    @MyAnnotation2(name = "Wang Wu")
    public void test() {
    }
    //When there is only one value by default, the element name can not be written
    @MyAnnotion3("subei")
    public void test2(){
    }
}
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation2 {
    // Annotated parameters: parameter type + parameter name ()
    // String name();
    String name() default "";
    int age() default 0;
    int id() default -1; // -1 means does not exist
    String[] schools() default {"bbb", "aaa"};
}
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotion3{
    String value();
}

reflex

Reflection mechanism

java Reflection

  • Reflection: is the key to java being regarded as a quasi dynamic language. The reflection mechanism allows the program to obtain the internal information of any class with the help of the Reflection API during execution, and can directly operate the internal properties and methods of any object
Class c=Class.forName("Java.lang.String")
  • After the Class is loaded, a Class object will be generated in the method area of heap memory. A Class has only one Class object, which contains complete Class structure information. We can see the structure of the Class through this object. This object is like a mirror clear lake. Through the lake, we can see the internal structure of the Class, so we call it "reflection".

To understand it with plug-ins in the game is: when the game is in progress, starting plug-ins is to create class objects during operation.

Normal method: you need to introduce the "package class" name > > > instantiate through the new method > > > get the instantiated object

Reflection method: instantiate the object > > > getclass() > > > to get the complete "package class" name

Reflection object

Advantages and disadvantages of reflection mechanism

  • advantage:
    • It can dynamically create objects and compile, reflecting great flexibility.
  • shortcoming
    • Performance impact. Using reflection is basically an interpretive operation. We can tell the JVM what we want to do and it meets our requirements. This kind of operation is always slower than directly performing the same operation.
public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        // Get class object through reflection
        Class name = Class.forName("github.Annotation.Demo01.User");
        System.out.println(name);
        Class c1 = Class.forName("github.Annotation.Demo01.User");
        Class c2 = Class.forName("github.Annotation.Demo01.User");
        Class c3 = Class.forName("github.Annotation.Demo01.User");
        Class c4 = Class.forName("github.Annotation.Demo01.User");
        /*
        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
        public native int hashCode();Returns the hash code value of the object
        Note: the hash value is a value calculated according to the hash algorithm. This value is related to the address value, but not the actual address value.
         */
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());
    }
}
// Entity class: pojo entity
class User{
    private int id;
    private int age;
    private String name;
    public User() {
    }
    public User(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 "User{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

Class class

introduce

  • The following methods are defined in the Object class, which will be inherited by all subclasses
    • public final Class getclass()
  • The type of the return value of the above method is a Class class, which is the source of Java reflection. In fact, the so-called reflection is also well understood from the running results of the program, that is, the name of the Class can be obtained through object reflection.

[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-lpxmbrdm-1636595385418) (C: \ users \ Z \ appdata \ roaming \ typora \ user images \ image-20211026210938059. PNG)]

  • The information that can be obtained after the object looks in the mirror: the attributes, methods and constructors of a Class, and which interfaces a Class implements. For each Class, JRE reserves an object of the same Cass type. A Class object contains information about a specific structure (class/interface/enum/annotation/ primitive type/void / []).
    • Class itself is also a class;
    • Class objects can only be created by the system;
    • A loaded Class will only have one Class instance in the JVM;
    • A Cass object corresponds to a class file loaded into JM;
    • Each Class instance will remember which Class instance it was generated from;
    • All loaded structures in a class can be completely obtained through class;
    • Class is the root of Reflection. For any class you want to dynamically load and run, you have to obtain the corresponding class object first.

Common methods of class

Method nameFunction description
static ClassforName (String name)Returns the class object with the specified class name name
Object newInstance ()Call the default constructor to return an instance of the Class object
getName ()Returns the name of the entity (Class, interface, array Class or void) represented by this Class object.
Class getSuperClass ()Returns the class object of the parent class of the current class object
Class[] getinterfaces ()Gets the interface of the current Class object
ClassLoader getclassLoader ()Returns the class loader for this class
Constructor getConstructors ()Returns an array containing some Constructor objects
Method getMothed (String name, Class...T)Returns a Method object whose formal parameter type is paramType
Field[] getDeclaredFields ()Returns an array of Field objects

Get an instance of Class

  • 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.
    • Class clazz=Person.class;
  • If the instance of a Class is known, call the getclass () method of the instance to obtain the Class object.
    • Class clazz= person. getClass();
  • If the full class name of a class is known and the class is in the class path, it can be obtained through the static method forName () of the class class, and ClassNotFound Exception may be thrown.
    • Class clazz Class forName("demo01 Student");
  • The built-in basic data type can directly use the class name. Type.
  • You can also use Classloader.
public class TestCreateClass {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("This man is:" + person);
        // Method 1: query by object
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
        // Method 2: forName
        Class c2 = Class.forName("github.Annotation.Demo01.Student");
        System.out.println(c2.hashCode());
        // Method 3: obtained by class name. Class
        Class c3 = Student.class;
        System.out.println(c3.hashCode());
        // Method 4: the packing classes of basic types have a Type
        Class c4 = Integer.TYPE;
        System.out.println(c4);
        // 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 = "student";
    }
}
class Teacher extends Person{
    public Teacher(){
        this.name = "teacher";
    }
}

What types can have Class objects

  • Class: external class, member (member internal class, static internal class), local internal class, anonymous internal class.
  • interface: interface
  • []: array
  • enum: Enumeration
  • annotation: annotation @interface
  • primitive type: basic data type
  • void
import java.lang.annotation.ElementType;
/**
 * Class of all types
 * @author subeiLY
 * @create 2021-06-07 14:50
 */
public class TestAllTypeClass {
    public static void main(String[] args) {
        Class c1 = Object.class;    // class
        Class c2 = Comparable.class;    // Interface
        Class c3 = String[].class; // One dimensional array
        Class c4 = int[][].class; // Two dimensional array
        Class c5 = Override.class; // annotation
        Class c6 = ElementType.class; // American TV Series
        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);
        // 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());
    }
}

java Memory Analysis

Java Memory

  • Heap:

    • new objects and arrays
    • It can be shared by all threads without storing other object references
  • Stack:

    • Store the basic variable type (including the specific value of this basic type)
    • The variable of the reference object (the specific address of the reference in the heap will be stored)
  • Method area:

    • Can be shared by all threads
    • Contains all class and static variables

Class loading process

There are three main steps:

  1. Loading phase
    • At this stage, the loader mainly works, that is, ClassLoader. The concept of loader will be discussed later!
    • The completed work is:
      • 1. Save the bytecode of the class file into memory to become the runtime data structure of the method area, as shown in the method area above
      • 2. Generate java.lang.Class objects in heap memory
  2. Link phase
    • The completed work is:
      • 1. Allocate memory for class variables (static) and assign default initial values! For example, static int a = 0; static String b = ""; this is the case.
      • 2. Assign a value to a constant value of a class. Let's understand this first. That is, constant values can be used at this stage!
  3. Initialization phase
    • This stage calls the class constructor to complete the work, as shown in the figure above
      • 1. The class variable is assigned a real value, that is, how much the variable is equal to in the code you write!
      • 2. Merge the statements in the static code block!
      • 3. When initializing a class, if the parent class is not initialized, the initialization of the parent class is triggered first

Class initialization

Active reference of class:

  • 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
  • Use the methods of the java.lang.reflect package to make reflection calls to the class
  • When initializing a class, if the parent class is not initialized, the parent class will be initialized first

Passive reference of class

  • When accessing a static code block, only the class that really lives in the code block will be initialized. For example, when the static variable of the parent class is referenced through the subclass, the subclass will not be initialized
  • Defining a class reference through an array does not trigger the initialization of this class
  • References to constants also do not trigger initialization
public class Demo5 {
    static {
        System.out.println("main Class is loaded");
    }
    public static void main(String[] args) throws ClassNotFoundException {
//        Active reference: load the parent class first and then the child class
//        Son son=new Son();
//        Reflection produces an active reference
//        Class.forName("com.reflection.Demo.Demo5");
//        A reference constant will not trigger the referenced method of a class, and calling a parent constant through a subclass will not trigger initialization
//          System.out.println(Son.b);
            System.out.println(Son.m);
    }
}
class Father{
    static int b=2;
    static{
        System.out.println("The parent class is loaded");
    }
}
class Son extends Father{
    static int c=3;
    static {
        System.out.println("Subclass loaded");
    }
        static final int m=1;
}

Class loader

Function: load the class file into memory, convert these static data into the runtime data structure of the method area, and then generate a java.lang.Class object representing this class in the heap as the access entry for the class data in the method area.

Class caching: the standard JavaSE class loader can i find classes as required, but once a class is loaded into the class loader, it will remain loaded for a period of time (caching). The JCM garbage collection mechanism can recycle cached class objects

There are three types of loaders:

  1. System loader: the loader of user-defined class you wrote is also the loader we use most. The parent loader is an extension loader, which can be referenced

    • //    Get system class loader
      ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
      
  2. Extension loader: the loader of the classes in the jar package stored in the jre/lib/ext directory. The parent loader is the root loader and can be referenced

    • // Get parent class loader of system class loader > > extension loader 
      ClassLoader sysParent = systemClassLoader.getParent();
      
  3. Root loader: the core class of Java is obtained through this loader, and we can obtain its reference, which is null

    • //Gets the parent class loader > > root loader of the extension class loader, but the obtained value is null 
      ClassLoader extParent = sysParent.getParent();
      
public class Demo1 {
    public Demo1() throws ClassNotFoundException {
    }
    public static void main(String[] args) throws ClassNotFoundException {
        //    Get system class loader
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);
        //sun.misc.Launcher$AppClassLoader@14dad5dc
//        Get parent class loader of system class loader > > extension loader
        ClassLoader sysParent = systemClassLoader.getParent();
        System.out.println(sysParent);
//        sun.misc.Launcher$ExtClassLoader@677327b6
//        Gets the parent class loader > > root loader of the extension class loader
        ClassLoader extParent = sysParent.getParent();
        System.out.println("ext:" + extParent);
//        null
//        Test which loader loads the current class
        ClassLoader classParent = Class.forName("com.ClassLoader.Demo.Demo1").getClassLoader();
        System.out.println("class:" + classParent);
//        class:sun.misc.Launcher$AppClassLoader@14dad5dc
//        Test who loaded the JDK built-in class
        ClassLoader jdkParent = Class.forName("java.lang.Object").getClassLoader();
        System.out.println("jdk:" + jdkParent);
//        jdk:null
//        Get the system classloader load path
        System.out.println(System.getProperty("java.class.path"));
//         . . . 
    }
}

Get class information

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


public class Demo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
//        Class c1=Class.forName("com.ClassLoader.Demo.User");
        User user=new User();
        Class c1=user.getClass();
        System.out.println(c1.getSimpleName());
        System.out.println("*************************");
//        Get class name + detailed path
        System.out.println(c1.getName());
//        Get the name of the class
        System.out.println(c1.getSimpleName());
//        Get the properties of this class
        Field[] fields=c1.getFields();      //The public attribute can be found
        fields=c1.getDeclaredFields();      //All attributes can be found
        for (Field field:fields) {
            System.out.println(field);
        }
        Field name=c1.getDeclaredField("name");
        System.out.println(name);
        System.out.println("*************************");
//        Get the method of the class
        Method[] methods=c1.getDeclaredMethods();
        for (Method method : methods) {     //Get all methods of this class and its parent class
            System.out.println("getDeclaredMethods:"+method);
        }
        System.out.println("*************************");
        Method[] methods1=c1.getMethods();
        for (Method method : methods1) {        //Get all methods of this class (and private methods)
            System.out.println("getMethods:"+method);
        }
        System.out.println("*************************");
//        Gets the specified method
//        Overload (parameter type needs to be specified to avoid this effect)
        Method getName=c1.getMethod("getName",null);
        Method setName=c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);
        System.out.println("*************************");
//        Gets the constructor of the specified instance object
        Constructor[] constructors=c1.getConstructors();//Get public method
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        Constructor[] constructors1=c1.getDeclaredConstructors();//Get all methods
        for (Constructor constructor : constructors1) {
            System.out.println(constructor);
        }
        System.out.println("*************************");
        //Gets the specified constructor
        Constructor declareConstructor=c1.getDeclaredConstructor(String.class,int.class,double.class);
        System.out.println(declareConstructor);
    }
}

Class object

  1. Create class objects, that is, instances. Normally, we create instances through new A(). Now we can create them through reflection

    1. //  Using the newInstance() method of Class class, the parameterless constructor is called to create an instance  
      Class aClass=Class.forName("com.ClassLoader.Demo.User"); User user1=(User) aClass.newInstance();
      
    2. // Not only can you create objects with a parameterless constructor, but also with a parameterless constructor
      // First, get the parameterized constructor through the getdeclaraedconstructor (corresponding parameter) method of Class class
      // Then you call the newInstance() method with the parameter constructor, and you can create the instance. 
      Constructor constructor=aClass.getDeclaredConstructor(String.class,int.class,double.class); User user2=(User) constructor.newInstance("xxx",xx,xx);//The number of parameters must be consistent, otherwise an exception occurs
      
  2. Through reflection, you can manipulate the methods and properties of the instance

    1. //        Call normal methods through reflection        
      User user= (User) aClass.newInstance();
      //        Get a method by reflection        
      Method setName=aClass.getDeclaredMethod("setName", String.class);
      //        inoke is activated, the instance is passed in as the first parameter, and the modified data is used as the second parameter 		  		 setName.invoke(user,"xxx");        
      System.out.println(user.getName());
      
    2. //        By reflecting operation attributes, private attributes cannot be directly operated. They can be turned off by closing the security detection of the program        
      User user4=(User) aClass.newInstance();        
      Field name=aClass.getDeclaredField("name");        
      name.setAccessible(true);       
      //The variable modified by private has a security protection mechanism,        
      name.set(user4,"xxx");        
      System.out.println(user4.getName());   
      

Annotation and reflection

import java.lang.annotation.*;
import java.lang.reflect.Field;
/**
 * @Description TODO
 * @Author Du
 * @declare:Annotation reflection exercise
 * @Date 2021/5/30 14:22
 */
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
    Class c1=Class.forName("com.AnnotationReflect.Demo.Student1");
//    Get annotations through reflection
    Annotation[] annotations=c1.getAnnotations();
    for (Annotation annotation : annotations) {
        System.out.println(annotation);
    }
//    Get the value of annotation value
    TableDu tableDu=(TableDu)c1.getAnnotation(TableDu.class);
    String value=tableDu.value();
    System.out.println(value);
//    Gets the annotation specified by the class
    Field field=c1.getDeclaredField("name");
    FiledStudent annotation=field.getAnnotation(FiledStudent.class);
    System.out.println(annotation.columName());
    System.out.println(annotation.type());
    System.out.println(annotation.length());
}
}
@TableDu("studentinfo")
class Student1{
    @FiledStudent(columName = "Sno",type="int",length = 10)
    private int id;
    @FiledStudent(columName = "Sname",type="int",length = 10)
    private String  name;
    @FiledStudent(columName = "Sex",type="int",length = 10)
    private String sex;
    public Student1(int id, String name, String sex) {
        this.id = id;
        this.name = name;
        this.sex = sex;
    }
    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;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledStudent{
    String columName();
    String type();
    int length();
}
//Annotation of class name
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableDu{
    String value();
}

Posted by rosieraz on Wed, 10 Nov 2021 17:49:37 -0800