1Annotation
- 注解本身对对代码逻辑没有任何影响
- SOURCE类型的注解在编译期就被丢掉了
- CLASS类型的注解仅保存在class文件中
- RUNTIME类型的注解在运行期可以被读取
- 如何使用注解由工具决定
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {int type() default 0;String level() default "info";String value() default "";
}@Report(type=1,level="error")
public class Person {}
因此如何处理注解只针对RUNTIME类型的注解
如何读取RUNTIME类型的注解
如何读取RUNTIME类型的注解?
- Annotation也是class
- 所有Annotation继承自java.lang.annotation.Annotation
- 使用反射API读取Annotation
- 方法1: 判断某个Annotation是否存在,存在再打印注解的信息
- Class.isAnnotationPresent(Class)
- Field.isAnnotationPresent(Class)
- Method.isAnnotationPresent(Class)
- Constructor.isAnnotationPresent(Class)
- 方法2:获取某个Annotation,注解对象不为空,再打印注解的信息
- Class.getAnnotation(Class)
- Field.getAnnotation(Class)
- Method.getAnnotation(Class)
- Constructor.getAnnotation(Class)
- getParameterAnnotations()
- 方法1: 判断某个Annotation是否存在,存在再打印注解的信息
Class cls = Person.class;
//判断@Report是否存在
cls.isAnnotationPresent(Report.class)Class cls = Person.class;
//获取Report的Annotation
Report report = cls.getAnnotation(Report.class);
int type = report.type();
String level = report.level();
//方法一:判断Annotation是否存在再读取
Class cls = Person.class;
if (cls.isAnnotationPresent(Report.class)) {Report report = cls.getAnnotation(Report.class);...
}//直接使用getAnnotation获取
Class cls = Person.class;
Report report = cls.getAnnotation(Report.class);
if(report != null){...
}
2读取方法参数的Annotation
public class Main {public static void main(String[] args) throws Exception{Person p1 = new Person("Xiao Ming", 25);Person p2 = new Person(null, 15);checkPerson(p1);checkPerson(p2);}static void checkPerson(Person p) throws Exception{System.out.println("check " + p + "...");Class c = Person.class;for (Field f : c.getFields()) {checkField(f,p);}}static void checkField(Field f, Person p) throws Exception{if (f.isAnnotationPresent(NotNull.class)) {Object r = f.get(p);if (r==null) {System.out.println("Error:field " + f.getName() + " is null...");}}if (f.isAnnotationPresent(Range.class)) {Range range = f.getAnnotation(Range.class);int n = (Integer) f.get(p);if (n < range.min() || n > range.max()) {System.out.println("Error:field " + f.getName() + " is out of range...");}}}}
public class Person {@NotNullpublic String name;@Range(max = 20)public int age;public Person(String name,int age) {this.name = name;this.age = age; }
}
//检查int类型的值在min到max之间
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Range {int min() default 1;int max() default 100;}
//检查字段不为空的注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NotNull {}
3总结
- 可以在运行期通过反射读取RUNTIME类型的注解,不要漏写@Retention(RetentionPolicy.RUNTIME)
- 可以通过工具处理注解来实现相应的功能
- 对JavaBean的属性值按规则进行检查
- JUnit会自动运行@Test注解的测试方法