class级注解仅存在于class文件的attribute区,jvm类加载时不解析、不挂载,仅供编译期工具如lombok使用,运行时反射调用返回null。

因为 RetentionPolicy.CLASS 注解虽然写入了 class 文件,但 JVM 类加载器在加载过程中根本不会解析它,也不会将其挂载到运行时的元数据结构中。
CLASS 级注解只存在于字节码的 attribute 区
编译器会把 CLASS 级注解(如 @Retention(RetentionPolicy.CLASS))写进 class 文件的 RuntimeVisibleAnnotations 或 RuntimeInvisibleAnnotations 属性里。这些是 class 文件规范定义的“附加信息”,和字段表、方法表一样属于静态元数据。
但它只是“存在”,不是“可用”——JVM 加载类时,只解析那些对运行时行为必需的部分(比如常量池、字段描述、方法签名、字节码),而注解 attribute 默认不在解析范围内。
JVM 不解析 CLASS 注解,元空间里不留痕
类加载的最终目标是构建可执行的运行时结构:Class 对象、Method 对象、Field 对象等。这些对象的内部字段(如 annotations)只在遇到 RUNTIME 级注解时,由 JVM 显式填充。
- SOURCE 级:编译后就没了,class 文件里压根没有
- CLASS 级:class 文件里有,但 JVM 加载时不读、不处理、不挂载
- RUNTIME 级:JVM 主动解析该 attribute,并把注解实例注入到反射对象中
丢弃不是错误,而是设计意图
CLASS 级注解面向的是构建期工具,比如 Lombok、MapStruct、某些 APT 处理器。它们在编译后、运行前扫描字节码,提取注解生成新代码或修改 class 结构。
对 JVM 来说,这类注解不参与任何运行时逻辑(如反射调用、动态代理、AOP 织入),所以不加载它,既节省内存,也避免无谓开销。
验证方式:反编译 + 反射对比
你可以用 javap -v MyClass 查看 class 文件,确认 CLASS 级注解确实出现在 RuntimeVisibleAnnotations 中;但运行时调用 method.getAnnotation(YourAnno.class) 一定返回 null,因为 JVM 没给它分配运行时身份。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











