转载:https://my.oschina.net/itblog/blog/1525665
写了一个自定义注解:
package com.my.test;
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.SOURCE)
public @interface MyAnnotation {
String value();
}
定义了一个类A,并用MyAnnotation标注。测试类中:
package com.my.test;
@MyAnnotation("This is MyAnnotation. ^_^")
class A {}
public class Test {
public static void main(String[] args) {
MyAnnotation annotation = A.class.getAnnotation(MyAnnotation.class);
if (annotation != null) {
System.out.println(annotation.value());
} else {
System.out.println("No such annotation.");
}
}
}
执行结果:
No such annotation.
如果把MyAnnotation类的Retention改为RetentionPolicy.CLASS,结果还是No such annotation。
如果改为RetentionPolicy.RUNTIME,此时的结果为:
This is MyAnnotation. ^_^
描述
在JavaDoc中,RetentionPolicy是这样描述的:
RetentionPolicy | 说明 | 举例 |
---|---|---|
SOURCE | 注解只保留在代码中,class文件中没有 | @Override, @SupressWarnings |
CLASS | 注解会保留在class文件中,但运行时不能取得 | @Override, @SupressWarnings |
RUNTIME | 注解会保留在class文件中,而且运行时可以取得 | @Deprecated |
可以理解的是,@Override注解只是为了编译器能检查是否当前的方法真的是在复写父类的方法,而@SuppressWarnings也只是为了抑制代码中的警告而已,在代码编译之后并没有作用,所以不需要写在CLASS文件中,于是,这类注解的RetentionPolicy自然应该为SOURCE。
验证
为了验证以上说明,接下来,我们使用javap工具把标注有MyAnnotation注解的类A的class文件进行反编译。
RetentionPolicy.SOURCE
RetentionPolicy.CLASS
可以看到:
- 中间包含了RuntimeInvisibleAnnotations这一部分,表明注解确实已经写入到class文件中,而且是运行时不可见的(RuntimeInvisibleAnnotations)
- 而在常量池中,可以清楚的看到自定义注解的权限定类名,注解的属性,和属性的值均被写入到class中,而且是常量
RetentionPolicy.RUNTIME
可以看到:
- 和CLASS一样,中间也包含了RuntimeInvisibleAnnotations这一部分,但注解是运行时可见的(RuntimeVisibleAnnotations)
- 和CLASS一样,注解的权限定类名,注解的属性,和属性的值同样被写入到class的常量池中
到这里可以得出以下结论:
- 一个带注解的类在编译后,如果注解的RetentionPolicy是CLASS或RUNTIME,那么此注解的信息会被记录到类的量池中
- 如果要在代码中获取注解,需要把Retention设置为RetentionPolicy.RUNTIME