Annotation
What is annotation
Annotation is a technology introduced from JDK5.0
- Role of annotation:
- It's not the program itself. You can explain the program (it doesn't make any difference if you drink notes on this point)
- It can be read by other programs (such as compiler)
- Format of annotation
- Annotations exist in the code as "@ annotation name". You can also add some parameter values, such as: @SuppressWarnings(value= "unchecked")
- Where are annotations 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 overriding annotations @Override public String toString() { return super.toString(); } //@Deprecated is not recommended for programmers. There may be risks or better ways, but it can be used @Deprecated public static void test(){ System.out.println("Deprecated"); } //@SuppressWarnings("all") is used to suppress warnings during compilation. Parameters need to be added. Parameters are already defined and can be used selectively @SuppressWarnings("all") public void test02(){ List list = new ArrayList(); }
Meta annotation
The function of meta annotation is to annotate other annotations. java defines four standard meta annotation types, which are used to explain other annotation types
- @Target: used to describe the scope of use of annotations (the described annotations can be used in the description)
- @Retention: indicates that the annotation information needs to be maintained at the description level to describe the annotation life cycle
- ( SOURCE < CLASS < RUNTIME )
- @Document: note that the annotation will be included in javadoc
- @Inherited: indicates that the subclass can inherit the annotation in the parent class
//Test meta annotation public class Test02 { @MyAnnotation public void test(){ } } //Define an annotation @Target(value = ElementType.METHOD)//This annotation can be placed on the method @Retention(value = RetentionPolicy.RUNTIME) @Documented //Indicates whether our annotations are generated in javadoc @Inherited @interface MyAnnotation{ }
Custom annotation
When using @interface custom annotation, it automatically inherits java lang.annotation. Annotation interface
//Custom annotation public class Test03 { //The annotation can display the assignment. If there is no default value, we must assign a value to the annotation @MyAnnotation2(name="hello") public void test(){ } @MyAnnotation3("world") public void test2(){ } } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2{ //Annotation parameters: parameter type + parameter name (); String name() default ""; int age() default 0; int id() default -1;//If the default value is -1, it means that it does not exist String[] schools() default {"hello","world"}; } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation3{ String value(); }
Reflection
Dynamic language:
- It is a kind of language that can change its structure at runtime, such as 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 certain conditions at run time
- Main dynamic languages: Object-C, c#, JavaScript, PHP, Python, etc.
Static language:
- Corresponding to dynamic languages, languages with immutable runtime structures are static languages. Such as Java, C, c++.
- Java is not a dynamic language, but it can be called a "quasi dynamic language". That is, Java is dynamic to some extent. We can use reflection mechanism to obtain characteristics similar to dynamic language. The dynamic nature of Java makes programming more flexible!
Java Reflection
Reflection is the key to Java being regarded as a dynamic language. The 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.
Class c = Class.forName("java.lang.String");
After loading the Class, an object of Class type (a Class has only one Class object) is generated in the method area of the heap memory, and this object contains the complete Class structure information. We can see the structure of the Class through this object. This Class is like a mirror, through which we can see the structure of the Class, so we vividly call it reflection
- Normal method: import the required "package class" name - > instantiate through new - > get the instantiated object
- Reflection method: instantiate object -- > getclass() method -- > get the complete "package class" name
package annotarion; //What is reflection public class Test04 { public static void main(String[] args)throws ClassNotFoundException { //Get the class object of the class through reflection Class c1 = Class.forName("annotarion.User"); System.out.println(c1); Class c2 = Class.forName("annotarion.User"); Class c3 = Class.forName("annotarion.User"); //A Class has only one Class object in memory //After a Class is loaded, the entire structure of the Class is encapsulated in the Class object System.out.println(c2.hashCode());//2003749087 System.out.println(c3.hashCode());//2003749087 } } //Entity class: pojo, entity class User{ private String name; private int id; private int age; 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 + '}'; } }
Class class
Common methods of Class
Method name | Function description |
---|---|
static ClassforName(String name) | Returns the Class object of 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() | Get the interface of the current Class object |
ClassLoader getClassLoader() | Return the class loader of 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[] getDeclasredFields() | Returns an array of Field objects |
Get an instance of Class
package annotarion; //Test the creation method of Class public class Test05 { public static void main(String[] args) throws ClassNotFoundException{ Person person = new Student(); System.out.println("This person is:"+person.name); //Method 1: obtain by object Class c1=person.getClass(); //Method 2: forname gets Class c2 = Class.forName("annotarion.Student"); //Method 3: pass the class name Class get Class c3 = Student.class; //Method 4: packing classes of basic built-in types have a Type attribute Class c4 = Integer.TYPE; //Get parent type c1.getSuperclass(); } } 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"; } }
Which types have Class objects
package annotarion; import java.lang.annotation.ElementType; //All types of classes public class Test06 { 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 object int[] a =new int[10]; int[] b =new int[100]; System.out.println(a.getClass().hashCode()); System.out.println(b.getClass().hashCode()); } }
Role of class loader
The function of class loading: load the bytecode content of the calss file into memory, convert these static data into the runtime data structure of the method area, and then generate a Java representing the Chinese class in the heap Lang.class object, as the access entry of 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 maintain loading (caching) for a period of time, but the jvm garbage collection mechanism can recycle these class classes
Class loaders are used to load classes into memory. The JVM specifies the following types of class loaders.
- Boot class loader: written in c++, it is the class loader of the JVM. It assigns a value to the java platform core library to load the core class library, which cannot be obtained directly
- Extension class loader: responsible for jar package or - D Java under jre/lib/ext directory Ext.dirs the jar under the specified directory is packaged into the working library
- System load class: responsible for java classpath or djava class. The classes and jar s in the directory referred to in path are packaged into the work, which is the most commonly used loader
package annotarion; public class Test08 { public static void main(String[] args) throws ClassNotFoundException{ //Get loader of system class ClassLoader classLoader = ClassLoader.getSystemClassLoader(); System.out.println(classLoader); //Get the parent class loader of the system class loader -- > extension class loader ClassLoader parent = classLoader.getParent(); System.out.println(parent); //Get the parent class loader -- > root loader of the extension class loader ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //Test which loader loads the current class ClassLoader classLoader1 = Class.forName("annotarion.Test08").getClassLoader(); System.out.println(classLoader1); //Test who loaded the built-in classes of jdk ClassLoader classLoader2= Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader2); //How to get the path that the system classloader can load System.out.println(System.getProperty("java.class.path")); } }
Create an object of a runtime class
Get the complete structure of the class runtime
package annotarion; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; //Get class information public class Test09 { public static void main(String[] args) throws ClassNotFoundException,NoSuchFieldException,NoSuchMethodException{ Class c1=Class.forName("annotarion.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 Field[] fields = c1.getFields();//Only public attribute can be found fields = c1.getDeclaredFields();//Find all attributes for (Field field:fields){ System.out.println(field); } //Get the value of the specified attribute Field name = c1.getDeclaredField("name"); System.out.println(name); //Get the method of the class Method[] methods=c1.getMethod(); for (Method method:methods){ System.out.println(method); } methods=c1.getDeclaredMethods(); for (Method method:methods){ System.out.println(method); } //Get the specified method Method getname=c1.getMethod("getName",null); Method setname=c1.getMethod("setName",String.class); System.out.println(getname); System.out.println(setname); //Get constructor of class Constructor[] constructors = c1.getConstructors(); for (Constructor constructor:constructors){ System.out.println(constructor); } constructors = c1.getDeclaredConstructors(); for (Constructor constructor:constructors){ System.out.println(constructor); } //Get the specified constructor Constructor declaredConstructors = c1.getDeclaredConstructors(String.class,int.class,int.class); System.out.println(declaredConstructors); } }
Dynamically create object execution methods
package annotarion; 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 Test10 { public static void main(String[] args) throws ClassNotFoundException,InstantiationException,IllegalAccessException,NoSuchMethodException,InvocationTargetException,NoSuchFieldException{ //Get calss object Class c1=Class.forName("annotarion.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 user1 = (User)constructor.newInstance("hello",001,18); System.out.println(user1); //Call normal methods through methods User user2 = (User)c1.newInstance(); //Get a method through reflection Method setName = c1.getDeclaredMethod("setName", String.class); //invoke: activate //(object, "value of method") setName.invoke(user2,"hello"); System.out.println(user2.getName()); //Operate attributes through reflection User user3 = (User)c1.newInstance(); Field name = c1.getDeclaredField("name"); //Private properties cannot be operated directly. We need to turn off the security detection, properties or methods of the program setAccessible(true); name.setAccessible(true); name.set(user3,"hello"); System.out.println(user3.getName()); } }
Performance comparison and analysis
package annotarion; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; //Analyze performance issues public class Test11 { //Call in normal mode public static void test01(){ User user = new User(); long startTime = System.currentTimeMillis(); for (int i = 0;i<100000000;i++){ user.getName(); } long endTime = System.currentTimeMillis(); System.out.println("Common way:"+(endTime-startTime)+"ms"); } //Reflection mode call public static void test02() throws NoSuchMethodException,IllegalAccessException, InvocationTargetException { User user = new User(); Class c1 =user.getClass(); Method getNmae=c1.getDeclaredMethod("getName",null); long startTime = System.currentTimeMillis(); for (int i = 0;i<100000000;i++){ getNmae.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("Reflection mode:"+(endTime-startTime)+"ms"); } //Reflection mode call, close detection public static void test03() throws NoSuchMethodException,IllegalAccessException, InvocationTargetException { User user = new User(); Class c1 =user.getClass(); Method getNmae=c1.getDeclaredMethod("getName",null); getNmae.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0;i<100000000;i++){ getNmae.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("Reflection mode off detection:"+(endTime-startTime)+"ms"); } public static void main(String[] args) throws NoSuchMethodException,IllegalAccessException, InvocationTargetException{ test01(); test02(); test03(); } } //Operation results //Normal mode: 4ms //Reflection mode: 288ms //Reflection mode off detection: 119ms
Reflection operation generics
package annotarion; 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 Test12 { 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 = Test12.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 method1 = Test12.class.getMethod("test01", null); Type genericReturnType = method1.getGenericReturnType(); if (genericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments =((ParameterizedType)genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument:actualTypeArguments){ System.out.println(actualTypeArgument); } } } }
Practice reflection operation annotation
package annotarion; import java.lang.annotation.*; import java.lang.reflect.Field; //Practice reflection operation annotation public class Test13 { public static void main(String[] args) throws ClassNotFoundException,NoSuchFieldException{ Class c1 =Class.forName("annotarion.Student2"); //Get annotations through reflection Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation :annotations){ System.out.println(annotation); } //Get the value of annotation value Tablea table=(Tablea)c1.getAnnotation(Tablea.class); String value = table.value(); System.out.println(value); //Get the annotation specified by the class Field f = c1.getDeclaredField("name"); Fielda annotation = f.getAnnotation(Fielda.class); System.out.println(annotation.columnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); } } @Tablea("student") class Student2{ @Fielda(columnName = "id",type = "int",length = 10) private int id; @Fielda(columnName = "age",type = "int",length = 10) private int age; @Fielda(columnName = "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; } } //Annotation of class name @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Tablea{ String value(); } //Annotation of attributes @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Fielda{ String columnName(); String type(); int length(); }