@retention和@target是最核心的两个元注解,前者控制注解生命周期(source/class/runtime),后者限定作用位置(如method、type等),共同决定注解能否被反射读取及适用场景。

Java 自定义注解需要通过元注解来声明其行为和作用范围,其中 @Retention 和 @Target 是最核心的两个元注解。它们分别控制注解的生命周期(保留在哪一阶段)和可应用的位置(类、方法、字段等),直接影响注解能否被反射读取、是否参与编译或生成字节码。
Retention:决定注解保留策略
@Retention 指定注解在哪个阶段还存在,有三个可选值:
-
RetentionPolicy.SOURCE:仅保留在源码中,编译时丢弃(如
@Override)。无法通过反射获取。 - RetentionPolicy.CLASS:保留在 class 文件中,但 JVM 不加载(默认策略)。运行时不可见,适用于字节码处理工具(如 ASM)。
- RetentionPolicy.RUNTIME:保留在 class 文件中且被 JVM 加载,可通过反射获取。这是自定义注解做运行时逻辑(如权限校验、序列化配置)的前提。
例如,若想用反射读取注解,必须显式声明:@Retention(RetentionPolicy.RUNTIME)
Target:限定注解使用位置
@Target 规定该注解能标注在哪些程序元素上,避免误用。常用 ElementType 值包括:
- ElementType.TYPE:类、接口、枚举、注解类型
- ElementType.METHOD:方法
- ElementType.FIELD:字段(含 enum 常量)
- ElementType.PARAMETER:方法参数
- ElementType.CONSTRUCTOR:构造方法
- ElementType.ANNOTATION_TYPE:注解类型本身(用于定义元注解)
支持多个位置时用数组形式:@Target({ElementType.METHOD, ElementType.TYPE})
组合使用示例
一个典型的运行时方法级注解定义如下:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecutionTime {
String value() default "default";
}
这样定义后,该注解只能加在方法上,且可在运行时通过 Method.getAnnotation(LogExecutionTime.class) 获取。
注意事项
- 不加 @Retention 时,默认为
CLASS,反射无法读取 —— 这是新手常见疏漏。 - 不加 @Target 时,默认允许标注在所有位置,可能引发语义混乱或编译器警告。
- 若注解自身也要被其他注解修饰(比如作为元注解),需额外加上
@Target(ElementType.ANNOTATION_TYPE)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











