Annotation and reflection

Keywords: Java

annotation

  • Function of annotation:

(1) It is not the procedure itself, which can be explained

(2) It can be read by other programs (such as compiler, etc.)

  • Format of Annotation:

Annotations exist in the code as "@ annotation name". You can also add some parameter values, such as @ SuppressWarnings(value="unchecked")

  • Where is Annotation used?

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 programming

Built in annotation

  • @Override

Defined in java.lang.Override, this annotation is only applicable to rhetoric, 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 is a better choice.

  • @SuppressWarnings

It is defined in java.lang.suppresswarnings to suppress warnings at compile time.

Different from the first two comments, you need to add a parameter to use it correctly. These parameters have been defined. Optional use.

@SupressWarnings("all")

@SupressWarnings("unchecked")

@Suppress warnings (value = {"unchecked", "depreciation"}) and so on

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)

(1)@Target: used to describe the scope of use of annotations (where the described annotations can be used)

(2)@Retention: indicates the level at which the annotation information needs to be saved, which is used to describe the annotation life cycle

(SOURCE < CLASS < RUNTIME)

(3)@Document: note that the annotation will be included in javadoc

(4)@Inherited: indicates that the subclass can inherit the annotation in the parent class

 import java.lang.annotation.*;
 ​
 //Test meta annotation
 @MyAnnotation
 public class Test02 {
 ​
     public void test(){
 ​
     }
 }
 ​
 //Define an annotation
 //Target indicates where our annotation can be used. The first value indicates that it can be used on methods and the second value indicates that it can be used on classes
 @Target(value = {ElementType.METHOD, ElementType.TYPE})
 ​
 //Retention indicates where our comments are still valid
 //runtime>class>sources
 @Retention(value = RetentionPolicy.RUNTIME)
 ​
 //Documented indicates whether our annotations are generated in JAVAdoc
 @Documented
 ​
 //A subclass can inherit the annotation of the parent class
 @Inherited
 @interface MyAnnotation{  //Define the annotation and modify it with public @interface
 ​
 }

Custom annotation

  • When using @ interface to customize annotations, it automatically inherits the java.lang.annotation.Annotation interface

  • analysis:

(1)@interface is used to declare an annotation. Format: public @interface annotation name {definition content}

(2) Each of these methods actually declares a configuration parameter

(3) The name of the method is the name of the parameter

(4) The return value type is the type of the parameter (the return value can only be the basic type, Class, String, enum)

(5) You can declare the default value of the parameter through default

(6) If there is only one parameter member, the general parameter name is value

(7) 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.*;
 ​
 //Custom annotation
 public class Test03 {
     //Annotations can display assignments. If there is no default value, we must assign a value to the annotation
     @MyAnnotation2(name = "Brandon")
     public void test(){
 ​
     }
 }
 ​
 @Target({ElementType.TYPE, ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 @interface MyAnnotation2{
     //Annotated parameters: parameter type + parameter name ();
     //Default is followed by the default value
     String name() default "";
     int age() default 0;
     int id() default -1;// If the default value is - 1, it means that it does not exist
 }

reflex

Reflection overview

Static VS dynamic language

Dynamic language

(1) It is a kind of language that can change its structure at run time: for example, new functions, objects and even code can be introduced, existing functions can be deleted or other structural changes. Generally speaking, the code can change its structure according to some conditions at run time.

(2) Main dynamic languages: Object-C, c#, JavaScript, PHP, Python, etc

Static language

(1) Corresponding to dynamic language, the language with immutable runtime structure is static language. Such as Java, C, C + +.

(2)Java is not a dynamic language, but Java can be called a "quasi dynamic language". That is, Java has certain dynamics. We can use reflection mechanism to obtain characteristics similar to dynamic language. The dynamic nature of Java makes programming more flexible.

 //JavaScript
 function f(){
     var x = "var a=3;var b=5;alert(a+b)"; //alert means pop-up window
     eval(x);  //Parse the corresponding string into js code and run it
 }

Java Reflection

  • Reflection is the key to Java being regarded as a 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 (you can obtain things decorated with private)

  Class c = Class.forName("java.lang.String")
  • After loading the Class, a Class object is generated in the method area of heap memory (a Class has only one Class object), which contains the complete Class structure information. We can see the structure of the Class through this object. This object is like a mirror, through which we can see the structure of the Class. Therefore, we vividly call it reflection

Normal method: import the required "package class" name ---- > instantiate through new ---- > to obtain the instantiated object

Reflection method: instantiate the object - > getClass () method - > get the complete "package class" name

Research and application of Java reflection mechanism

  • Functions provided by Java reflection mechanism

(1) Determine the class of any object at run time

(2) Construct an object of any class at run time

(3) Judge the member variables and methods of any class at run time

(4) Get generic information at run time

(5) Call the member variables and methods of any object at run time

(6) Process comments at run time

(7) Generate dynamic proxy

(8)......

  • Advantages and disadvantages of Java reflection

(1) Advantages:

It can dynamically create objects and compile, reflecting great flexibility.

(2) Disadvantages:

It has an impact on performance. Using reflection is basically an interpretation operation. We can tell the JVM what we want to do and it meets our requirements. Such operations are always slower than performing the same operation directly.

  • Main API s related to reflection

(1) java.lang.Class: represents a class

(2) java.lang.reflect.Method: method representing a class

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

(4) java.lang.reflect.Constructor: constructor representing a class

(5)......

Class class

The following methods are defined in the Object class, which will be inherited by all subclasses

 public final Class getClass()

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.

 package reflection;
 ​
 //What is reflection
 public class Test02 {
     public static void main(String[] args) throws ClassNotFoundException {
         //Gets the Class object of the Class through reflection
         //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
         Class c1 = Class.forName("reflection.User");//Under the reflection package
         System.out.println(c1);  //Output class reflection.User
         
         c1.get....();//Get the information in the class
     }
 }
 ​
 //Entity class: there are only attributes in it. pojo,entity
 class User{
     private String name;
     private int id;
     private int age;
 ​
     //Construction method shortcut key alt+insert
     //Select multiple shift + click the last option
     public User() {
     }
 ​
     public User(String name, int id, int age) {
         this.name = name;
         this.id = id;
         this.age = age;
     }
 ​
     public String getName() {
         return name;
     }
 ​
     public void setName(String name) {
         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;
     }
 ​
     @Override
     public String toString() {
         return "User{" +
                 "name='" + name + '\'' +
                 ", id=" + id +
                 ", age=" + age +
                 '}';
     }
 }
  • The information that can be obtained after the object looks in the mirror: the properties, methods and constructors of a Class, and which interfaces a Class implements. For each Class, the JRE reserves an invariant Class object for it. A Class object contains information about a specific structure (class/interface/enum/annotation/primitive type/void / []).

(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 file loaded into the JVM

(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 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
Object newInstance()Call the default constructor to return an instance of the Class object (create a reflective object)
getName()Returns the name of the entity (Class, interface, array or void) represented by this Class object. (get the name of the Class)
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

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 has the highest program performance.

 Class clazz = Person.class;

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

 Class clazz = person.getClass();

3. 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 Class class, and ClassNotFoundException may be thrown

 Class clazz = Class.forName("demo01.Student");

4. The built-in basic data type can directly use the class name. Type

5. You can also use ClassLoader to explain later

  • The code is implemented as follows:

 package reflection;
 ​
 //What are the creation methods of the test class
 public class Test03 {
     public static void main(String[] args) throws ClassNotFoundException {
         Person person = new Student();
         System.out.println("This man is" + person.name);
 ​
         //Method 1: obtained by object
         Class c1 = person.getClass();
         System.out.println(c1.hashCode());//Compared with the following, they are the same
 ​
         //Method 2: obtain forName and throw an exception
         Class c2 = Class.forName("reflection.Student");
         System.out.println(c2.hashCode());
 ​
         //Method 3: obtained by class name. Class
         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; //class of Integer
         System.out.println(c4);  //Output int
 ​
         //Get parent type
         Class c5 = c1.getSuperclass();
         System.out.println(c5);  //Output class reflection.Person
     }
 }
 ​
 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() {
         this.name = "student";
     }
 }
 ​
 class Teacher extends Person{
     public Teacher() {
         this.name = "teacher";
     }
 }

What types can have Class objects?

1.class: external class, member (member internal class, static internal class), local internal class, anonymous internal class

2.interface: Interface

3. []: array

4.enum: Enumeration

5.annotation: annotation @ interface

6.primitive type: basic data type

7.void

 import java.lang.annotation.ElementType;
 ​
 //Class of all types
 public class Test04 {
     public static void main(String[] args) {
         Class c1 = Object.class;  //Class of class
         Class c2 = Comparable.class;  //Class of interface
         Class c3 = String[].class;  //One dimensional array
         Class c4 = int[][].class;  //Two dimensional array
         Class c5 = Override.class;  //annotation
         Class c6 = ElementType.class;  //Enumeration type
         Class c7 = Integer.class;  //Basic data type
         Class c8 = void.class;  //void
         Class c9 = Class.class;  //Class is also a class
 ​
         //alt plus mouse selection, you can copy and paste vertically
         System.out.println(c1); //class java.lang.Object
         System.out.println(c2); //interface java.lang.Comparable
         System.out.println(c3); //class [Ljava.lang.String;
         System.out.println(c4); //class [[I
         System.out.println(c5); //interface java.lang.Override
         System.out.println(c6); //class java.lang.annotation.ElementType
         System.out.println(c7); //class java.lang.Integer
         System.out.println(c8); //void
         System.out.println(c9); //class java.lang.Class
 ​
         //A Class has only one Class object
         //As long as the element type is the same as the dimension (one-dimensional, two-dimensional, etc.), it is the same Class
         int[] a = new int[10];
         int[] b = new int[100];
         System.out.println(a.getClass().hashCode());//1956725890
         System.out.println(b.getClass().hashCode());//1956725890
     }
 }

Class load memory analysis

Java Memory Analysis

heapnew objects and arrays
It can be shared by all threads without storing other object references
java Memory AnalysisStackStore the basic variable type (it will contain 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 areaCan be shared by all threads
Contains all class and static variables

The method area is a special heap.

Class loading process (understand)

When a program actively uses a class, if the class has not been loaded into memory, the system will initialize the class through the following three steps.

1. Class loading

Read the class file of the class into memory and create a java.lang.Class object for it. This is done by the class loader.

2. Class link

Merge the binary data of the class into the JRE.

3. Class initialization

The JVM is responsible for initializing the class.

Class loading and ClassLoader understanding

 package reflection;
 ​
 public class Test05 {
     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.Link, m=0 after link
         3.initialization
         <clinit>(){
                     System.out.println("A Class static code block initialization "");
                     m = 300;
                     m = 100;
         }
          */
     }
 }
 ​
 class A{
     static {
         System.out.println("A Class static code block initialization");
         m =300;
     }
 ​
     static int m =100;
 ​
     public A(){
         System.out.println("A Class");
     }
 }
 //Output results
 //Class A static code block initialization
 //Class A parameterless construction initialization
 //100
  • The above codes are stored in memory as follows:

First, the basic data of the class is generated in the method area. When the class is loaded, the class object has been generated in the heap.

Generate objects in the heap during new A (), and then find A's own class class (only one).

 

Class initialization

  • When does class initialization occur?

1. Active reference of class (class initialization must occur)

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

(2) new is an object of a class

(3) Call static members (except final constants) and static methods of the class

(4) Use the methods of the java.lang.reflect package to make reflection calls to the class

(5) When initializing a class, if its parent class is not initialized, its parent class will be initialized first

2. Passive reference of class (class initialization will not occur)

(1) When accessing a static domain, only the class that actually declares the domain will be initialized. For example, when the static variable of the parent class is referenced through the subclass, the subclass will not be initialized. (the static variable has been completed when linking)

(2) Defining a class reference through an array does not trigger the initialization of this class

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

 //When will the test class initialize
 public class Test06 {
     static {
         System.out.println("Main Class is loaded");
     }
 ​
     public static void main(String[] args) throws ClassNotFoundException {
         //1. Active call
         //(1) new is a class
         Son son = new Son();
 ​
         //Output results
         //The Main class is loaded
         //The parent class is loaded
         //Subclass loaded
 ​
         //(2) Reflection also produces active references
         Class.forName("reflection.Son");
 ​
         //Output results
         //The Main class is loaded
         //The parent class is loaded
         //Subclass loaded
 ​
         //2. Methods that do not generate class references
         //(1) Access the static domain of the parent class through the subclass
         System.out.println(Son.b);
 ​
         //Output results
         //The Main class is loaded
         //The parent class is loaded
         //2
 ​
         //(2) Array, class will not be loaded (class reference is defined through array)
         Son[] array = new Son[5];
 ​
         //Output results
         //The Main class is loaded
 ​
         //(3) Constants in constant pool
         System.out.println(Son.M);
 ​
         //Output results
         //The Main class is loaded
         //1
     }
 }
 ​
 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");
         m = 300;
     }
 ​
     static int m = 100;
     static final int M = 1;
 }

Class loader

Role of 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.lang.Class object representing this class in the heap as the access entry to the class data in the method area.

  • Class caching: the standard Java se class loader can find classes as required, but once a class is loaded into the loader, it will remain loaded (cached) for a period of time. However, the JVM garbage collection mechanism can recycle these class objects.

  • The class loader is used to load classes into memory. The JVM specification defines loaders for classes of the following types.

(1) Boot class loader

Written in C + +, it is the loader of the JVM. It is responsible for the Java platform core library (rt.java package) and is used to load the core class library. The loader cannot be obtained directly.

(2) Extended class loader

Be responsible for packaging the jar package under jre/lib/ext directory or the jar package under the directory specified by - D java.ext.dirs into the working library.

(3) System class loader

It is responsible for packing classes and jar s in the directory indicated by java -classpath or - D java.class.path. It is the most commonly used loader.

 package reflection;
 ​
 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);
 ​
         //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 + +)
         //The root loader (boot class loader) cannot get directly, so the result is null
         ClassLoader parent1 = parent.getParent();
         System.out.println(parent1);
 ​
         //Test which class loads the current class (the custom class is loaded by the system loader)
         ClassLoader classLoader = Class.forName("reflection.Test07").getClassLoader();
         System.out.println(classLoader);
 ​
         //Test who loaded the JDK built-in classes (root loader)
         classLoader = Class.forName("java.lang.Object").getClassLoader();
         System.out.println(classLoader);
 ​
         //How to get the path that the system class loader can load
         System.out.println(System.getProperty("java.class.path"));
     }
 }
 //Output results
 //sun.misc.Launcher$AppClassLoader@18b4aac2
 //sun.misc.Launcher$ExtClassLoader@74a14482
 //null
 //sun.misc.Launcher$AppClassLoader@18b4aac2
 //null
 ​
 /*
 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;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jfxrt.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\localedata.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\nashorn.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunec.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunjce_provider.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunmscapi.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunpkcs11.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\zipfs.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\javaws.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\jce.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfr.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfxswt.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\jsse.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\management-agent.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\plugin.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\resources.jar;
 C:\Program Files\Java\jdk1.8.0_201\jre\lib\rt.jar;
 D:\IntelliJ Idea\JavaSE\out\production\Basic grammar;
 D:\IntelliJ Idea\IntelliJ IDEA 2020.2.3\lib\idea_rt.jar
  */

Create an object for the runtime class

Gets the complete structure of the runtime class

  • Get the complete structure of the runtime class through reflection

Field,Method,Constructor,Superclass,Interface,Annotation

(1) All interfaces implemented

(2) Inherited parent class

(3) All constructors

(4) All methods

(5) All fields

(6) Annotation

(7).......

 package reflection;
 ​
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 ​
 //Get class information
 public class Test08 {
     public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
         Class c1 = Class.forName("reflection.User"); //User is an entity class
 ​
         //Find class by object
         //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
 ​
         //Only public properties can be found
         //Field[] fields = c1.getFields();
 ​
         //All properties found
         Field[] fields = c1.getDeclaredFields();
         for(Field field:fields){
             System.out.println(field);
         }
 ​
         //Gets the value of the specified property
         Field name = c1.getDeclaredField("name");
         System.out.println(name);
 ​
         //Method to get class
         System.out.println("==================================================");
         Method[] methods = c1.getMethods();  //Get all 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("getDeclaredMethods" + method);
         }
 ​
         //Gets the specified method
         //The latter requires parameters to represent the type of input parameters in the method, because the method has overloads to distinguish
         System.out.println("==================================================");
         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();  //Get public constructor
         for(Constructor constructor:constructors){
             System.out.println(constructor);
         }
         constructors = c1.getDeclaredConstructors();  //Get all constructors
         for(Constructor constructor:constructors){
             System.out.println("getDeclared" + constructor);
         }
 ​
         //Gets the specified constructor
         Constructor declaredConstructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
         System.out.println("appoint:" + declaredConstructor);
 ​
     }
 }
 //reflection.User
 //User
 //private java.lang.String reflection.User.name
 //private int reflection.User.id
 //private int reflection.User.age
 //private java.lang.String reflection.User.name
 //==================================================
 //Normal: public java.lang.String reflection.User.toString()
 //Normal: public java.lang.String reflection.User.getName()
 //Normal: public int reflection.User.getId()
 //Normal: public void reflection.User.setName(java.lang.String)
 //Normal: public int reflection.User.getAge()
 //Normal: public void reflection.User.setAge(int)
 //Normal: public void reflection.User.setId(int)
 //Normal: public final void java.lang.Object.wait() throws java.lang.InterruptedException
 //Normal: public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
 //Normal: public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
 //Normal: public boolean java.lang.Object.equals(java.lang.Object)
 //Normal: public native int java.lang.Object.hashCode()
 //Normal: public final native java.lang.class (Java. Lang.Object. GetClass)
 //Normal: public final native void java.lang.Object.notify()
 //Normal: public final native void java.lang.Object.notifyAll()
 //getDeclaredMethodspublic java.lang.String reflection.User.toString()
 //getDeclaredMethodspublic java.lang.String reflection.User.getName()
 //getDeclaredMethodspublic int reflection.User.getId()
 //getDeclaredMethodspublic void reflection.User.setName(java.lang.String)
 //getDeclaredMethodspublic int reflection.User.getAge()
 //getDeclaredMethodspublic void reflection.User.setAge(int)
 //getDeclaredMethodspublic void reflection.User.setId(int)
 //==================================================
 //Gets the specified method
 //public java.lang.String reflection.User.getName()
 //public void reflection.User.setName(java.lang.String)
 //==================================================
 //Gets the specified constructor
 //public reflection.User()
 //public reflection.User(java.lang.String,int,int)
 //getDeclaredpublic reflection.User()
 //getDeclaredpublic reflection.User(java.lang.String,int,int)
 //Specify: public reflection.User(java.lang.String,int,int)
  • Summary:

(1) In the actual operation, the operation code to obtain the class information is not often developed

(2) Be familiar with the function and reflection mechanism of java.lang.reflect package

(3) How to get properties, methods, constructor names, modifiers, etc

What can I do with a Class object?

  1. You can create a Class object: call the newInstance() method of the Class object

(1) Class must have a parameterless constructor

(2) The constructor of the class needs sufficient access rights

reflection? Can't you create an object without a parameterless constructor? As long as the constructor in the class is explicitly called during the operation and the parameters are passed in, the operation can be instantiated.

  • The steps are as follows:

(1) Get the specified parameter type constructor of 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) Instantiate objects through Constructor

  1. Call the specified method

Through reflection, the Method in the class is called and completed through the Method class.

(1) Get a Method object through the getMethod(String name, Class... parameterTypes) Method of Class class, and set the parameter type required for this Method operation.

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

 

Object invoke(Object obj, Object[] args)

  • Object corresponds to the return value of the original method. If the original method has no return value, null is returned

  • If the original method is static, the formal parameter Object obj is null

  • If the original method parameter list is empty, Object[] args is null

  • If the original method is declared as private, you need to explicitly call the setAccessible(true) method of the method object before calling the invoke () method to access the private method

setAccessible

  • Method, Field and Constructor objects all have setAccessible methods.

  • setAccessible is a switch that enables and disables access security checks

  • If the parameter value is true, it indicates that the Java language access check should be cancelled when the reflected object is used

(1) Improve the efficiency of reflection. If reflection must be used in the code, and the code of this sentence needs to be called frequently, please set it to true

(2) So that private members that cannot be accessed can also be accessed

  • If the parameter is false, it indicates that the reflected object should implement Java language access check

 package reflection;
 ​
 import javax.jws.soap.SOAPBinding;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 ​
 //Dynamically create objects through reflection
 public class Test09 {
     public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
         //Get Class object
         Class c1 = Class.forName("reflection.User");
 ​
         //Construct an object
         //User user = (User)c1.newInstance();
         //It was originally created as an Object class, which is strongly changed to User here
         //Essentially, a parameterless constructor is called!
         //System.out.println(user);  // Output User{name='null', id=0, age=0}
 ​
         //Creating objects through constructors
         //Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
         //User user2 = (User)constructor.newInstance("Qinjiang", 001,18);
         //System.out.println(user2);  // Output User{name = 'Qinjiang', id=1, age=18}
 ​
         //Call normal methods through reflection
         User user3 = (User)c1.newInstance();
         //Get a method by reflection
         Method setname = c1.getDeclaredMethod("setName", String.class);
         //invoke activates this method
         //(object, "value of method")
         setname.invoke(user3, "Mad God");
         System.out.println(user3.getName());  //Output madness
 ​
         //Operation properties by reflection
         System.out.println("===========Operation properties by reflection=============");
         User user4 = (User)c1.newInstance();
         Field name = c1.getDeclaredField("name");
         //Private properties cannot be operated directly. You need to turn off the security detection of the program
         //Cancel security detection so that private properties can be accessed through reflection
         name.setAccessible(true);
         name.set(user4, "Mad god 2");
         System.out.println(user4.getName());  //Output fury 2
     }
 }

Performance comparison and analysis

 package reflection;
 ​
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 ​
 //Analyze performance issues
 //The time taken for this method to execute 1 billion
 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("Execute 1 billion in the normal way:" + (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("Execute 1 billion in reflection mode:" + (endTime-startTime) + "ms");
     }
 ​
     //Reflection method call close check
     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("Turn off the detection reflection mode and execute 1 billion of this:" + (endTime-startTime) + "ms");
     }
 ​
     public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         test01();
         test02();
         test03();
         //Execute 1 billion in ordinary way: 5ms
         //Reflection mode: 2811 MS
         //Turn off the detection reflection mode and execute 1 billion times: 1380ms
     }
 }

Reflection operation generics (understand)

  • Java uses the generic erasure mechanism to introduce generics. Generics in Java are only used by the compiler javac to ensure data security and avoid forced type conversion. However, once the compilation is completed, all types related to generics are erased.

  • In order to manipulate these types through reflection, Java has added ParameterizedType, GenericArrayType, TypeVariable and WildcardType to represent types that cannot be classified into Class but have the same name as the original type. (understand)

  • ParameterizedType: represents a parameterized type, such as collection < string > (generic type)

  • GenericArrayType: indicates that an element type is a parameterized type or an array type of type variable

  • TypeVariable: it is the public parent interface of each type variable

  • WildcardType: represents a wildcard type expression

 package reflection;
 ​
 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){  //Judge whether genericParameterType belongs to parameterized type
                 Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();//Get real parameter type
                 for (Type actualTypeArgument : actualTypeArguments) {
                     System.out.println(actualTypeArgument);
                 }
             }
             System.out.println("");
         }
 ​
         //The output results are as follows:
         //#java.util.Map<java.lang.String, reflection.User>
         //class java.lang.String
         //class reflection.User
         //
         //#java.util.List<reflection.User>
         //class reflection.User
 ​
         method = Test11.class.getMethod("test02", null);
         Type genericReturnType = method.getGenericReturnType();  //Get return value type
         if(genericReturnType instanceof ParameterizedType){  //Determine whether genericReturnType is a parameterized type
             Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();//Get real parameter type
             for (Type actualTypeArgument : actualTypeArguments) {
                 System.out.println(actualTypeArgument);
             }
         }
 ​
         //Output results
         //class java.lang.String
         //class reflection.User
     }
 }

Reflection operation annotation

  • getAnnotations

  • getAnnotation

Practice ORM

  • What is ORM?

(1) Object relationship mapping -- > object relationship mapping

 

(2) Class corresponds to table structure

(3) Attribute corresponds to field

(4) Object corresponds to record

(5) Requirement: use annotation and reflection to complete the mapping relationship between class and table structure

 package reflection;
 ​
 import java.lang.annotation.*;
 import java.lang.reflect.Field;
 ​
 //Practice reflection operation annotation
 public class Test12 {
     public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
         Class c1 = Class.forName("reflection.Student2");
 ​
         //Get annotations through reflection
         Annotation[] annotations = c1.getAnnotations();
         for (Annotation annotation : annotations) {
             System.out.println(annotation);
         }
         //Output @ reflection.Tablekuang(value=db_student)
 ​
 ​
         //Gets the value of the annotated value
         //Annotation[] annotation = c1.getAnnotations(Tablekuang.class);
         Tablekuang tablekuang = (Tablekuang)c1.getAnnotation(Tablekuang.class);
         String value = tablekuang.value();
         System.out.println(value);  //Output db_student
 ​
 ​
         //Gets the annotation specified by the class
         Field f = c1.getDeclaredField("name");  //name or id or age
         Fieldkuang annotation = f.getAnnotation(Fieldkuang.class);
         System.out.println(annotation.columnName());  //Output db_name
         System.out.println(annotation.type());  //Output varchar
         System.out.println(annotation.length());  //Output 3
     }
 }
 ​
 @Tablekuang("db_student")
 class Student2{
     @Fieldkuang(columnName = "db_id",type = "int",length = 10)
     private int id;
     @Fieldkuang(columnName = "db_age",type = "int",length = 10)
     private int age;
     @Fieldkuang(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)  //Act on class
 @Retention(RetentionPolicy.RUNTIME)
 @interface Tablekuang{  //value is equivalent to the table name
     String value();
 }
 ​
 //Attribute annotation
 @Target(ElementType.FIELD)  //Act on attributes
 @Retention(RetentionPolicy.RUNTIME)
 @interface Fieldkuang{
     String columnName();
     String type();
     int length();
 }

Posted by truckie2 on Tue, 14 Sep 2021 14:21:40 -0700