Annotation and reflection
annotation
What is annotation
Annotation is a technology introduced by JDK5
Annotation is to explain the procedure
What's the difference between annotation and annotation
Annotations are explained to programs, and annotations are explained to people
Format of annotation:
Annotations exist in the code as "@ annotation name". You can also add parameter values, such as @ SuppressWarning (value = "unchecked")
Where can annotations be used
It can be used in package, class, method, field, etc., which is equivalent to auxiliary functions. We can access these metadata through reflection mechanism programming
Built in annotation
The built-in annotation is the annotation provided by the program
Three commonly used built-in annotations:
-
@Override
Represents overriding a method declaration in a superclass
-
@Deprecated
Indicates abandoned, not recommended
-
@SuppressWarnings
Indicates that the warning message is ignored
parameter | explain |
depreciation | Warning that an obsolete class or method was used |
unchecked | Warning when an unchecked transformation is performed, such as: no generics are specified when using a collection |
fallthrough | case penetration occurs when used in a switch statement |
path | There is a warning that the path does not exist in the classpath and source file path |
serial | Warning when a serialVersionUID definition is missing on a serialized class |
finally | Warning when any finally clause cannot be completed |
all | Warnings about all of the above |
In the above table are some parameters of @ suppressWarnings annotation, which can be used as needed
@suppressWarnings("finally")
@suppressWarnings(value={"unchecked","path"})
Meta annotation
Function of meta annotation:
The function of meta annotation is to annotate other annotations. Four standard meta annotation types are defined in java, which are used to describe the types of other annotations
These types are in java.lang.annotation:
- @Target: used to describe the scope of use of annotations, such as classes and methods
- @Retention: indicates the level at which the annotation information needs to be saved. It is used to describe the annotation life cycle, generally in 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
package com.annotation.Demo; import com.sun.istack.internal.Interned; import java.lang.annotation.*; /** * Meta annotation */ public class AnnotationDemo1 { // Annotation can display assignment. If there is no default value, we must assign a value to the annotation // For example, in annotation 2 below // If you don't assign a value, it will be red @annotation2(age = 22) public void test2() { } // There is a default value in the annotation. It does not assign a value and does not affect the operation and compilation of the program @annotation3(age = 11) public void test3() { } //When there is only one parameter, you can directly use value instead of other names @annotation1(value = "11", age = 11,cource = 11.1) public void test() { } @annotation public void test4(){ } } @Target({ElementType.TYPE, ElementType.METHOD}) @interface annotation2 { int age(); } //Annotation parameters: can'shu'lei'can'shu'lei'xt({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @interface annotation1 { String value(); int age(); double cource(); } @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @interface annotation3 { // String name() default "Xiao Ming"; The default value is followed by default and the default value String name() default "Xiao Hong"; int age(); } @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @interface annotation{ //The default value is "" 0 "". "" String name() default ""; int age() default 0; }
analysis:
- When @ interface customizes annotations, it automatically inherits the java.lang.annotation.Annotation interface
- @Interface is used to declare an annotation. Format: public @interface annotation name (custom content)
- Each method 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, etc.)
- You can declare the default value of the parameter through default
- When there is only one parameter member, the general parameter name is value
- The annotation element must have a value. When we customize the annotation element, we often use an empty string with 0 as the default value
reflex
Reflection mechanism
java Reflection
- Reflection: it is the key to java being regarded as a quasi dynamic language. Reflection mechanism refers to that the program obtains the internal information of any class with the help of Reflection API during execution, and can directly operate the internal properties and methods of any object
Get class
//The first method is implemented through the static method of Class - forName() class1 = Class.forName("com.xxxx.User"); //The second way is through the class attribute of the class class1 = Object.class; //The third way is through the object getClass method Object obj = new Object(); Class<?> class1 = obj.getClass();
- 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 import the "package class" name > > > instantiate through the new method > > > get the instantiated object
Reflection method: instantiate Object > > > getclass() > > > get the complete "package class" name
Basic operation of reflection
Class aClass = Class.forName("com.xxxx.User"); //Get full class name String name = aClass.getName(); //Get a simple class name String simpleName = aClass.getSimpleName(); //Get the public field of the class according to the field name Field field = aClass.getField("age"); //Gets the method of the class according to the method name Method declaredMethod = aClass.getDeclaredMethod("getName");
Class instantiation
Class aClass = Class.forName("com.xxxx.User"); //It is directly instantiated through the class class and uses the parameterless constructor of the User class User user = (User) aClass.newInstance();
Call the method of the class
//First, you need to obtain the Method object corresponding to the Method Method method = class1.getDeclaredMethod("setAge", int.class); //Calls the specified function and passes arguments method.invoke(obj, 28);
Research and application of Java reflection mechanism
Functions provided by Java reflection mechanism:
- Determine the class of any object at run time
- Construct an object of any class at run time
- Judge the member variables and methods of any class at run time
- Call the member variables and methods of any object at run time
- Get generic information at run time
- Processing annotations at run time
- Generate dynamic proxy
Class class
Class is very important for reflection. The information obtained by an object after reflection: the attributes, methods and constructors of a class, which interfaces a class implements and which classes it inherits. For each class, JRE reserves an object of constant class type. A class object contains class, interface, enum and annotation of a specific structure , primitive type, void, [] and other related information
- Class itself is a class
- Class objects can only be created by the system
- A loaded Class has only one Class instance in the JVM
- A class object corresponds to a. Class file loaded into the JVM
- 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
Method name | Function 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 |
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 getMethod(String name,Class... T) | Returns a Method object whose formal parameter type is paramType |
Field[] getDeclaredFields() | Returns an array of Field objects |
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
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
- Class loading: read the class file of the class into memory and create a java.lang.Class object for it. This process is completed by the class loader
- Class Link: merge the binary data of the class into the JRE
- Class initialization: the JVM is responsible for initializing the class
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 to class:
- When accessing a static code block, only the class that actually declares 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; }
Role of 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 cache: the standard JavaSE class loader can find classes as required, but once a class is loaded into the class loader, it will remain loaded for a period of time (CACHE). The gc garbage collection mechanism can recycle the cached class objects
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
package com.ClassLoader.Demo; 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 System.out.println("getMethods:"+method); } System.out.println("*************************"); // Gets the specified method // heavy load 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 loading and ClassLoader understanding
What can you do with a Class object?
Create Class object: call newInstance () method of Class object
- Class must have a parameterless constructor
- The constructor of the class needs sufficient access rights
//Get Class object Class aClass=Class.forName("com.ClassLoader.Demo.User"); // Construct an object Essentially, a parameterless constructor is called User user1=(User) aClass.newInstance(); System.out.println(user1); //Result: y name isnull,my id is 0i got 0.0points // You can not only create objects with a parameterless constructor, but also with a parameterless constructor Constructor constructor=aClass.getDeclaredConstructor(String.class,int.class,double.class); User user2=(User) constructor.newInstance("zhangsan",1,99.9);//The number of parameters must be consistent, otherwise an exception occurs System.out.println(user2); //Running result: my name is Du, my id is 1i got 99.9points
If you do not know the number and type of parameters of the Class object, you can obtain information through Field
//Note: if you don't know how many variables the Class object has, you can get information through Field Field[] fields=aClass.getDeclaredFields(); for (Field field : fields) { System.out.println(field); }
Call normal methods through reflection
// Call normal methods through reflection User user= (User) aClass.newInstance(); // Get a method by reflection Method setName=aClass.getDeclaredMethod("setName", String.class); // inoke means active setName.invoke(user,"zhangsan"); System.out.println(user.getName());
Operation properties by reflection
// 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); //Can pass. The variables modified by private have a security protection mechanism, name.set(user4,"zhangsan"); System.out.println(user4.getName()); }
Call the specified method
Through reflection, the Method in the class is called and completed through the Method class
- Obtain a Method object through the getMethod(String name,Class... parameterTypes) Method of Class class, and set the parameter type required for this Method operation.
- Use Object invoke (Object obj,Object []) to call and pass the parameter information of the ovj object to be set to the method
- If the return value of the Object object method or the original method has no return value, the run result returns null
- If the original method is static, the formal parameter Object can be null
- If the original method parameter list is empty, Object args is null
- If the original method is declared private private, you need to call the setAccessible(true) of the method object before invoke(), so that you can make a violent reflection.
About setAccessible(), its function is to start and disable the switch of security check. When the Boolean value is true, the java program cancels the access check, and when false, starts the access check.
- It improves the efficiency of reflection. If reflection must be used in code, this method is essential
- Can make inaccessible private members be forcibly accessed
Full Demo
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Demo3 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //Get Class object Class aClass=Class.forName("com.ClassLoader.Demo.User"); // Construct an object // Essentially, a parameterless constructor is called User user1=(User) aClass.newInstance(); System.out.println(user1); //Result: y name isnull,my id is 0i got 0.0points // You can not only create objects with a parameterless constructor, but also with a parameterless constructor Constructor constructor=aClass.getDeclaredConstructor(String.class,int.class,double.class); User user2=(User) constructor.newInstance("zhangsan",1,99.9);//The number of parameters must be aligned with that of getdeclaraedconstructor() System.out.println(user2); //Running result: my name iszhangsan,my id is 1i got 99.9points //Note: if you don't know how many variables the Class object has, you can get information through Field // Field[] fields=aClass.getDeclaredFields(); // for (Field field : fields) { // System.out.println(field); // } // Call normal methods through reflection User user= (User) aClass.newInstance(); // Get a method by reflection Method setName=aClass.getDeclaredMethod("setName", String.class); // inoke means active setName.invoke(user,"zhangsan"); System.out.println(user.getName()); // 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); //Can pass. The variables modified by private have a security protection mechanism, name.set(user4,"zhangsan"); System.out.println(user4.getName()); } }
Performance comparison
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Demo4 { // Normal execution public static void test1(){ User user=new User(); long startTime=System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { user.getName(); } long endTime=System.currentTimeMillis(); System.out.println("1 billion times in ordinary way"+(endTime-startTime)+"ms"); } // Reflection mode execution public static void test2() 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("1 billion times in reflection mode"+(endTime-startTime)+"ms"); } // Turn off detection reflection mode execution public static void test3() 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 for 1 billion times"+(endTime-startTime)+"ms"); } public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { test1(); test2(); test3(); } }
Get annotation information through reflection
package com.AnnotationReflect.Demo; import java.lang.annotation.*; import java.lang.reflect.Field; 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 TableLong tableLong=(TableLong)c1.getAnnotation(TableLong.class); String value=tableLong.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()); } } @TableLong("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 TableLong{ String value(); }