RetentionPolicy.SOURCE注解未写入字节码,如何在运行时访问?
关于
RetentionPolicy.SOURCE注解运行时访问的问题 嘿,我来给你掰扯清楚这个事儿哈!首先得明确一个核心点:RetentionPolicy.SOURCE类型的注解,确实会在编译完成后被丢弃,不会被写入字节码——但这并不意味着你完全没法访问注解里的东西,得看你要访问的是什么。
先搞懂:你例子里的MyAnno.a到底是什么?
你定义的MyAnno是个注解,但里面的int a = 4;可不是注解的属性哦!在Java里,注解本质是一种特殊的接口,而在接口里定义的变量默认就是**public static final的静态常量**。哪怕这个注解是SOURCE级别的,MyAnno这个注解类本身还是会被编译成.class文件的——SOURCE策略只丢弃的是注解的使用实例(比如你给某个方法加@MyAnno(val=xxx)),而注解类本身不会被丢。
所以你例子里的MyAnno.a,其实就是普通的接口静态常量,和注解的保留策略压根没关系,运行时直接通过类名访问完全没问题。
补全代码验证一下
把你的代码补全后,运行起来完全正常:
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.SOURCE) @interface MyAnno { int a = 4; // 静态常量,属于MyAnno接口的成员 int val(); // 这才是注解的属性,只有注解实例被保留时才能获取 } public class Example { public static void test() { System.out.println("MyAnno.a = " + MyAnno.a); } public static void main(String[] args) { test(); } }
编译运行后,控制台会输出:MyAnno.a = 4,完美运行。
关键区别:注解属性 vs 静态成员
这里一定要分清两个东西:
- 注解属性(比如
val()):只有当注解的保留策略是CLASS或RUNTIME时,你才能通过反射获取到某个类/方法上的注解实例,进而拿到val的值。如果是SOURCE级别的,编译后注解实例就没了,根本拿不到。 - 注解类的静态常量(比如
a):这是注解类(接口)本身的成员,只要注解类被编译成.class文件,运行时就能直接访问,和注解的保留策略无关。
所以结论就是:你例子里的代码本身就可以直接运行访问MyAnno.a,不需要额外操作——因为它是静态常量,和注解的Retention策略没关系~
内容的提问来源于stack exchange,提问作者1 JustOnly 1
相关产品推荐
相关产品推荐

