java注解本质是附加在程序元素上的元数据,本身不执行逻辑,而是通过@retention控制生命周期、@target约束作用位置,结合反射在运行时驱动行为;java 8扩展了类型注解和重复注解机制。

Java 注解本质是**附加在程序元素上的元数据**,它本身不执行逻辑,而是为编译器、工具或运行时框架提供结构化信息。理解其原理,关键在于抓住两个核心:**生命周期控制(@Retention)** 和 **作用位置约束(@Target)**。Java 8 的类型注解是对这一机制的重要扩展,让注解能深入到“类型使用”层面,不再局限于声明处。
注解不是注释,而是一种可被程序读取的接口
每个注解在编译后都对应一个继承自 java.lang.annotation.Annotation 的特殊接口。JVM 在运行时通过反射获取注解对象,实际返回的是一个由 JVM 动态生成的代理类实例——这意味着你调用 annotation.value() 看似在访问字段,实则是触发代理的 invoke() 方法。这种设计既保持了语法简洁,又实现了元数据与逻辑的解耦。
@Retention 决定注解“活多久”,这是功能生效的前提
注解能否被反射读取,完全取决于 @Retention 的取值:
-
SOURCE:仅存在于源码,编译后消失。如
@Override、@SuppressWarnings,只供编译器检查。 - CLASS:写入 .class 文件,但类加载时不保留。默认值,适合编译期代码生成(如 Lombok)。
-
RUNTIME:保留在运行时内存中,可通过
Class.getAnnotation()或Method.getAnnotation()获取。Spring 的@Transactional、自定义校验注解必须设为此值。
很多自定义注解“不起作用”,根本原因就是漏写了 @Retention(RetentionPolicy.RUNTIME)。
Java 8 类型注解:把标记能力从“声明”延伸到“使用”
Java 8 新增 ElementType.TYPE_USE 和 ElementType.TYPE_PARAMETER,让注解能标注在更细粒度的类型上下文中:
-
TYPE_PARAMETER:用于泛型类型参数声明,例如:
class Box { ... } -
TYPE_USE:覆盖所有“使用类型”的场景,包括:
– 创建对象:new @Immutable ArrayList<string>()</string>
– 强制转换:Object o = "hello"; String s = (@NonNull String) o;
– 方法参数类型:void process(@ReadOnly List data)
– 泛型实参:List
这类注解通常配合编译期检查工具(如 Checker Framework)使用,实现更严格的静态类型安全,比如空值检查、不可变性验证、资源泄漏预防等,把部分运行时错误提前到编译阶段捕获。
重复注解:解决“同一位置需多个同类标记”的需求
Java 8 之前,若想在同一个方法上加多个 @Role("ADMIN") 和 @Role("USER"),只能包装成容器注解:@Roles({@Role("ADMIN"), @Role("USER")})。Java 8 引入 @Repeatable 后,只需:
- 定义注解时标注
@Repeatable(Roles.class); - 提供一个值为该注解数组的容器注解
@interface Roles; - 即可直接写:
@Role("ADMIN") @Role("USER") public void doAction() { ... }。
语法更自然,语义更清晰,也便于框架统一扫描处理。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











