自定义注解类反编译后表现为继承java.lang.annotation.Annotation的接口,而非普通类;其属性被编译为无参、无实现的抽象方法,default值存于class文件的AnnotationDefault属性中。

自定义注解类在反编译后,看到的不是普通类,而是一个继承了 java.lang.annotation.Annotation 的特殊接口。它没有方法体、不包含逻辑实现,所有“属性”都表现为抽象方法声明。
反编译后的真实结构示例
假设你定义了这样一个注解:
@Target(ElementType.METHOD)<br>@Retention(RetentionPolicy.RUNTIME)<br>public @interface Log {<br> String value() default "info";<br> int level() default 1;<br>}
用 javap -s Log.class 反编译后,实际看到的是:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
public interface Log extends java.lang.annotation.Annotation {<br> public abstract java.lang.String value();<br> public abstract int level();<br>}
注意几点:
- 关键字是
interface,不是class - 自动继承
java.lang.annotation.Annotation - 每个属性对应一个无参、无修饰符、无实现的抽象方法
- 即使写了
default "info",反编译结果里也不会出现default关键字——默认值信息存储在 class 文件的AnnotationDefault属性中,javap默认不显示,需加-v参数查看详细字节码
为什么是接口而不是类?
这是 Java 语言规范强制规定的:
- 所有注解类型在语义上都是
Annotation的子类型 - JVM 在运行时通过反射获取注解实例时,会动态生成一个代理类(
Proxy实例),该代理实现了你的注解接口,并将属性值封装在内部 - 接口天然不可实例化、无状态、只声明契约,符合注解作为“元数据标记”的定位
常见误区澄清
不要误以为反编译看到的接口就是你写的源码原样。真实 class 文件中还隐含了关键元数据:
-
RuntimeVisibleAnnotations属性:记录该类/方法/字段上用了哪些注解 -
AnnotationDefault属性:存放default值(如value() default "info") -
Signature属性:支持泛型注解时的类型签名(Java 8+)
这些结构不会直接出现在 javap 的默认输出里,但它们才是 JVM 和反射机制真正读取的内容。

















