@retention用于指定注解的生命周期,source级仅存于源码、class级存于class文件但反射不可见、runtime级可在运行时通过反射获取;默认为class级,自定义业务注解通常需显式声明为runtime。

@Retention 用于指定注解的生命周期,即该注解在源码、编译后 class 文件、还是运行时还存在。它不决定“能不能用”,而是决定“什么时候还能拿到这个注解”。
注解的三个保留级别
Java 提供了三种 RetentionPolicy 枚举值:
-
SOURCE:只保留在源代码中,编译时被丢弃。比如
@Override、@SuppressWarnings就是 SOURCE 级别,编译器用完就扔,class 文件里没有。 - CLASS:保留在 class 文件中,但 JVM 加载类时不会加载到内存(反射拿不到)。默认值,适合字节码处理工具(如 ASM、Javassist)使用。
-
RUNTIME:保留在 class 文件中,且 JVM 运行时会加载进内存,可通过反射获取。自定义业务注解(如 Spring 的
@Autowired、MyBatis 的@Select)基本都用这个级别。
怎么写一个 RUNTIME 级别的注解
定义注解时,加上 @Retention(RetentionPolicy.RUNTIME) 即可:
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
String value() default "method";
}
这样你就能在运行时用反射读取它:
Method method = targetClass.getMethod("doSomething");
if (method.isAnnotationPresent(LogExecutionTime.class)) {
LogExecutionTime ann = method.getAnnotation(LogExecutionTime.class);
System.out.println(ann.value()); // 输出 "method"
}
常见误区提醒
- 没加
@Retention时,默认是CLASS,反射拿不到——容易误以为注解“没生效”。 -
@Retention必须作用在注解定义上,不能加在普通类或方法上。 - 即使设为
RUNTIME,也得配合反射主动读取,JVM 不会自动执行注解里的逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











