Annotation and reflection
1.1 notes
Function of Annotation
- It is not the procedure itself, which can be explained
- It can be read by other programs (such as compiler, etc.)
Built in annotation
@Override : this comment applies only to rhetorical devices, indicating that one method declaration intends to override another method declaration in the superclass
@Deprecated : this comment can be used to modify methods, attributes and classes, indicating that programmers are not encouraged to use such elements. Usually, it is dangerous or there is a better choice.
@SuppressWarnings("all"): used to suppress compile time warnings all the time
example:
import java.util.ArrayList; import java.util.List; //What is annotation public class Test01 extends Object{ //@Override annotation @Override public String toString() { return super.toString(); } //Deprecated is not recommended for programmers, but it can be used. Or there is a better way @Deprecated public static void test(){ System.out.println("Deprecated"); } @SuppressWarnings("all") //Suppression warning public void test02(){ List list = new ArrayList(); } public static void main(String[] args) { test(); } }
1.2 meta annotation
The function of meta annotation is to annotate other annotations.
example:
//Test meta annotation import java.lang.annotation.*; public class Test02 { } //Define an annotation //Target indicates where our annotations can be used @Target(value = {ElementType.METHOD,ElementType.TYPE}) //Retention indicates where our annotation is still valid //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 MyAnnotation{ }
1.3. User defined annotation
use @interface Custom annotation
example:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //Custom annotation public class Test03 { //Annotations can display assignments. If there is no default value, we must assign a value to the annotation @MyAnnotation2(age =18,name = "ss") public void test(){ } @MyAnnotation3("ss") public void test1(){ } } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2 { //Annotated parameters: parameter type + parameter name (); String name() default ""; int age(); int id() default -1;//If the default value is - 1, it means that it does not exist. String[] schools() default {"Hubei University","Zhixing College"}; } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation3{ String value(); }
1.4 reflection
Reflection is the key to java being regarded as a dynamic language. Reflection mechanism allows programs to obtain 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
Advantages and disadvantages of reflection
advantage:
It can dynamically create objects and compile, reflecting great flexibility
Disadvantages:
Impact on Performance
example:
//What is reflection public class Test02 { public static void main(String[] args) throws ClassNotFoundException { //Gets the Class object of the Class through reflection Class c1 = Class.forName("com.ss.reflection.User"); System.out.println(c1); Class c2 = Class.forName("com.ss.reflection.User"); Class c3 = Class.forName("com.ss.reflection.User"); Class c4 = Class.forName("com.ss.reflection.User"); //A Class is loaded in memory with only one Class object //After a class is loaded, the whole structure of the class will be encapsulated in the Cla object System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); System.out.println(c4.hashCode()); } } //Entity class: POJO: entity class User{ private String name; private int id; private int age; 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 + '}'; } }
1.5 common methods of Class
[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-jh9benyu-1627644107765) (C: \ users \ 2239871144 \ appdata \ roaming \ typora \ typora user images \ image-20210513105252194. PNG)]
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. The full Class name of a Class is known. Under the path of cutting the Class, it can be obtained through the static method forName() of Class class, and ClassNotException 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
5. You can also use ClassLoader
example:
//What are the creation methods of test Class public class Test03 { public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); System.out.println("This person is:"+person.name); //Method 1: obtained by object Class c1 =person.getClass(); System.out.println(c1.hashCode()); //Method 2: forname Class c2 = Class.forName("com.ss.reflection.Student"); System.out.println(c2.hashCode()); //Method 3: pass the class name Class get Class c3 = Student.class; System.out.println(c3.hashCode()); //Method 4: wrapper classes of basic built-in types have a Type attribute Class c4 = Integer.TYPE; System.out.println(c4); //Get parent type Class c5 = c1.getSuperclass(); System.out.println(c5); } } 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"; } }
Summary
import java.lang.annotation.ElementType; //Class of all types public class Test04 { 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;//enumeration 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()); } }
1.6. Extension class loader
-
Class loading
When a program wants to use a class, if the class has not been loaded into memory, the system will initialize the class through three steps: loading, connecting and initialization
-
load
This is to read the class file into memory and create a class object for it. When any class is used, the system will create a class object
-
connect
Verify whether there is a correct internal structure and is consistent with other classes
Preparation is responsible for allocating memory for static members of the class and setting default initialization values
The process of resolving the symbolic reference (constant name) in the virtual machine constant pool and replacing it with a direct reference (address)
-
initialization
The JVM initializes classes
The process of executing a class constructor () method. The class constructor () method is generated by automatically collecting the assignment actions of all class variables in the class at compile time and combining the statements in the static code block. (the class constructor is used to construct class information, not the constructor to construct the class object)
When initializing a class, if it is found that its parent class has not been initialized, the initialization of its parent class needs to be triggered first
Virtual chance ensures that the () methods of a class are properly locked and synchronized in a multithreaded environment
-
-
Class loading process
- Create an instance of a class
- Class, or assign a value to a static variable
- Class
- Use reflection to force the creation of Java. Net corresponding to a class or interface Lang.class object
- Initializes a subclass of a class
- Directly use Java Exe command to run a main class
-
Class loader
Be responsible for The Class file is loaded into the intrinsic and the corresponding Class object is generated for it
-
Composition of class loader
-
System ClassLoader
It is responsible for loading the class file from the java command, as well as the jar package and classpath specified by the classpath environment variable when the JVM starts
-
Extension ClassLoader extension classloader
Be responsible for loading jar packages in JRE's extension directory, and the ext directory under JRE's lib directory in JDK
-
Bootstrap ClassLoader root classloader
Also known as boot class loader, it is responsible for loading Java core classes and is written in C + +
-
example:
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 + +) ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //Test which loader the current class is ClassLoader classLoader = Class.forName("com.ss.reflection.Test07").getClassLoader(); System.out.println(classLoader); //Test who loaded the JDK built-in class 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")); } }
1.7. Get the complete construction of runtime class
Get the complete structure of the runtime class through reflection
Field,Method,Constructor,Superclass,Interface,Annotation
example:
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("com.ss.reflection.User"); //Get the name of the class System.out.println(c1.getName());//Get package name + class name System.out.println(c1.getSimpleName());//Get class name //Get the properties of the class System.out.println("==============="); Field[] fields = c1.getFields();//Only public properties can be found fields = c1.getDeclaredFields();//All properties found 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(); for (Method method :methods) { System.out.println("natural:"+method); } methods = c1.getDeclaredMethods(); for (Method method :methods) { System.out.println("getDeclaredMethods:"+method); } //Gets the specified method Method getName = c1.getMethod("getName", null); Method setName = c1.getMethod("setName", String.class); System.out.println(getName); System.out.println(setName); //Gets the specified constructor System.out.println("===================="); Constructor[] constructors = c1.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } constructors = c1.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } //Gets the specified constructor Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class); System.out.println("#"+declaredConstructor); } }
1.8. Create objects dynamically through reflection
example:
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("com.ss.reflection.User"); //Construct an object //User user = (User) c1.newInstance();// The essence is to call the parameterless constructor of the class // System.out.println(user); //Creating objects through constructors // Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class); // User user2 = (User) constructor.newInstance("ss",001, 18); // System.out.println(user2); //Call normal methods through reflection User user3 = (User)c1.newInstance(); //Get a method by reflection Method setName = c1.getDeclaredMethod("setName", String.class); //invoke: activate //(object, "value of method") setName.invoke(user3,"ss"); System.out.println(user3.getName()); //Operation properties by reflection System.out.println("====================="); User user4 = (User)c1.newInstance(); Field name = c1.getDeclaredField("name"); //Private properties cannot be operated directly. We need to turn off the security detection of the program and setAccessible(true) of properties or methods name.setAccessible(true); name.set(user4,"ss"); System.out.println(user4.getName()); } }
1.9 performance comparison between ordinary mode call and reflection mode call
setAccessible
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; //Analyze performance issues public class Test10 { //Normal mode call public static void Test01(){ User user = new User(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { user.getName(); } long endTime = System.currentTimeMillis(); System.out.println("1 billion times in ordinary 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("1 billion times in reflection mode:"+(endTime-startTime)+"ms"); } //Reflection mode call, turn off detection public static void Test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName", null); getName.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { getName.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("Close the detection mode for 1 billion times:"+(endTime-startTime)+"ms"); } public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Test01(); Test02(); Test03(); } }
2.0 reflection operation generics
example:
import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; //Get generics through reflection public class Test11 { public void test01(Map<String,User>map,List<User> list){ System.out.println("test01"); } public Map<String, User> Test02(){ System.out.println("Test02"); return null; } public static void main(String[] args) throws NoSuchMethodException { Method method = Test11.class.getMethod("test01", Map.class, List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println("#"+genericParameterType); if (genericParameterType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } method = Test11.class.getMethod("test02",null); Type genericReturnType = method.getGenericReturnType(); if (genericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } }
2.1. Reflection operation notes
getAnnotations
getAnnotation
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("com.ss.reflection.Student2"); //Get annotations through reflection Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //Gets the value of the annotation Tabless tabless = (Tabless)c1.getAnnotation(Tabless.class); String value = tabless.value(); System.out.println(value); //Gets the annotation specified by the class Field f = c1.getDeclaredField("id"); Filedss annotation = f.getAnnotation(Filedss.class); System.out.println(annotation.columnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); } } @Tabless("db_student") class Student2{ @Filedss(columnName = " db_id",type = "int",length = 10) private int id; @Filedss(columnName = " db_age",type = "int",length = 10) private int age; @Filedss(columnName = " db_name",type = "varchar",length = 3) private String name; public Student2() { } public Student2(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student2{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; } } //Annotation of class name @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Tabless{ String value(); } //Attribute annotation @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Filedss{ String columnName(); String type(); int length(); }