Predefined annotations in JDK
@override: check whether the annotated method inherits from the parent class (Interface)
@Deprecated: the content of this annotation indicates that it is obsolete
@SuppressWarnings: suppress warnings
//Suppress all warnings that may pop up in the current class are suppressed @SuppressWarnings("all") public class stu { String name; //All warnings for the current method are suppressed @SuppressWarnings("all") public void show() { System.out.println("Student's name:"+name); } }
Custom annotation
Format:
Meta annotation public @interface Annotation name() { Attribute list; }
Essence: Annotation is an interface, which inherits the Annotation interface by default
Properties: abstract methods in interfaces
requirement:
The return type of the property consists of the following values:
- Basic data type
- String
- enumeration
- annotation
- Arrays of the above types
The attribute is defined, and it needs to be assigned a value when it is used
- If the default keyword is used to initialize the default value when defining an attribute, the attribute can not be assigned when annotation is used
- If only one attribute needs to be assigned and the name of the attribute is value, value can be omitted and the value can be defined directly
- When assigning an array value, the value is wrapped with {}. If there is only one value in the array, {} can be omitted
demonstration
Custom annotation class:
package reflect; public @interface annto { int age(); String name(); Per p(); ann2 anno2(); String[] strs(); }
stu class:
package reflect; @annto(age=18,name="Huyou ",p=Per.perople,anno2=@ann2,strs={"Huyou ","children"}) public class stu { String name; public void show() { System.out.println("Student's name:"+name); } }
Meta annotations: annotations that describe annotations
@Target: describes where the annotation can work
ElementType value:
- TYPE: can act on a class
- METHOD: can act on methods
- FIELD: can act on member variables
//value can be omitted. The following writing method can act on classes, methods and member variables at the same time @Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD}) //@Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD}) public @interface ann2 { }
@Retention: describes the stage in which annotations are retained
//The annotation currently described will be retained in the bytecode file and read by the JVM @Retention(RetentionPolicy.RUNTIME)
@Documented: describes whether annotations are extracted into api documents
@Inherited: describes whether the annotation is inherited by subclasses'
@Inherited public @interface ann2 { }
For the class or member method annotated with ann2 below, its subclasses will also be annotated with ann2
Use (parse) annotations in the program: get the attribute values defined in the annotations
Gets the object (class, method, field) of the annotation definition location
Gets the specified annotation
getAnnotation(class) //In fact, it is to generate a subclass implementation object of the annotation interface in memory public class ProImp1 implements ann2 { public String ClassName() { return "reflect.stu"; } public String MethodName() { return "show"; } }
Call the abstract method in the annotation to obtain the configured property value
demonstration:
Requirements: do not change any code of the class, create any object of the class, and execute any method of the class
ann2 annotation class:
package reflect; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ann2 { String ClassName(); String MethodName(); }
stu class:
package reflect; public class stu { String name; public void show() { System.out.println("Student's name:"+name); } }
main function:
package reflect; import java.io.InputStream; import java.lang.reflect.Method; import java.util.Properties; @ann2(ClassName = "reflect.stu",MethodName = "show") public class main { public static void main(String[] args) throws Exception { //1. Get the bytecode file object of this class Class<main> mainClass=main.class; //2. Get the annotation object above ann2 a2=mainClass.getAnnotation(ann2.class); //In fact, it is to generate a subclass implementation object of the annotation interface in memory /* public class ProImp1 implements ann2 { public String ClassName() { return "reflect.stu"; } public String MethodName() { return "show"; } }*/ //3. Call the abstract method defined in the annotation object to obtain the return value String className=a2.ClassName(); String methodName=a2.MethodName(); //3. Load this class into memory Class cls=Class.forName(className); //4. Create object Object obj=cls.newInstance(); //5. Get method object Method method=cls.getMethod(methodName); //6. Implementation method method.invoke(obj); } }
Simple test framework
main:
package reflect; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Method; /* * After the main method is executed, it will automatically execute all the detected methods (Methods annotated with check). If the method has exceptions, the exceptions will be recorded in the file * */ public class checkTest { public static void main(String[] args) throws IOException { //1. Create a computer object calculator c=new calculator(); //2. Get bytecode file object Class cls=c.getClass(); //3. Get all methods Method[] methods=cls.getDeclaredMethods(); //Record the number of exceptions int number=0; BufferedWriter bw=new BufferedWriter(new FileWriter("bug.txt")); for(Method method:methods) { //4. Judge whether there is a check comment on the method if(method.isAnnotationPresent(check.class)) { //5. Yes, implementation try { method.invoke(c); } catch (Exception e) { //6. Catch exception //Record to file number++; bw.write(method.getName()+"The method is abnormal"); bw.newLine(); bw.write("The name of the exception:"+e.getCause().getClass().getSimpleName()); bw.newLine(); bw.write("Cause of abnormality"+e.getCause().getMessage()); bw.newLine(); bw.write("------------------------------------------"); bw.newLine(); } } } bw.write("A total of"+number+"Secondary anomaly"); bw.flush(); bw.close(); } }
calculator:
package reflect; public class calculator { @check public void add() { System.out.println("a+b=Huyou "); } @check public void minus() { System.out.println("1/0="+1/0); } @check public void div() { String str=null; str.toString(); } }
check:
package reflect; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /*You need to add @ Retention(RetentionPolicy.RUNTIME) to the custom annotation to declare that the annotation's survival policy can be retained until runtime, and then it can be obtained correctly through reflection.*/ @Retention(RetentionPolicy.RUNTIME) public @interface check { }
Test results:
bug.txt:
minus The method is abnormal Name of exception:ArithmeticException Cause of abnormality/ by zero ------------------------------------------ div The method is abnormal Name of exception:NullPointerException Cause of abnormality Cannot invoke "String.toString()" because "str" is null ------------------------------------------ There were 2 exceptions in this test