Java注解本质是继承Annotation接口的特殊接口,需用@interface定义并配合@Target和@Retention元注解;属性以无参方法声明,支持默认值、数组及重复注解,运行时通过反射读取。

Java 注解本质是接口,由编译器在编译期或运行时通过反射读取并处理。自定义带属性的注解,核心在于声明一个用 @interface 定义的接口,并为它添加方法(即“属性”),再配合元注解控制其作用范围和生命周期。
1. 基础语法:用 @interface 定义注解
注解不是类,而是特殊接口,所有注解都隐式继承 java.lang.annotation.Annotation。属性以无参方法形式声明,返回类型有限制(基本类型、String、Class、枚举、其他注解,以及以上类型的数组)。
例如,定义一个带 name 和 value 属性的注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiLog {
String value() default ""; // 默认空字符串
String name() default "default";
int level() default 1;
}2. 必须搭配的元注解
自定义注解需至少指定 @Target 和 @Retention,否则无法正常使用:
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
立即学习“Java免费学习笔记(深入)”;
-
@Target:指定注解可用的位置,如
ElementType.METHOD(方法)、ElementType.TYPE(类)、ElementType.FIELD(字段)等;可传数组,支持多位置 -
@Retention:指定注解存活时间:
SOURCE(仅源码)、CLASS(字节码,但不加载到 JVM)、RUNTIME(运行期可通过反射获取)——带属性且需动态读取的注解必须选RUNTIME - 可选:
@Documented(生成 Javadoc 时包含该注解)、@Inherited(子类可继承父类上的该注解)
3. 使用注解并读取属性值
在目标元素上使用注解后,需通过反射获取其实例并调用对应方法读取属性:
@ApiLog(value = "用户登录", name = "auth", level = 2)
public void login() { /* ... */ }
<p>// 反射读取
Method m = clazz.getDeclaredMethod("login");
if (m.isAnnotationPresent(ApiLog.class)) {
ApiLog anno = m.getAnnotation(ApiLog.class);
System.out.println(anno.value()); // "用户登录"
System.out.println(anno.name()); // "auth"
System.out.println(anno.level()); // 2
}4. 高级技巧:支持数组、默认值与重复注解
- 数组属性写法:
String[] tags() default {"api"};,使用时可写@ApiLog(tags = {"v1", "auth"}) - 若只有一个属性且名为
value(),使用时可省略名称:@ApiLog("hello")等价于@ApiLog(value = "hello") - 要支持重复使用同一注解(如多个
@Role("ADMIN")),需定义容器注解 + 添加@Repeatable:
@Repeatable(Roles.class)
public @interface Role {
String value();
}
<p>public @interface Roles {
Role[] value();
}之后就能在同一个元素上写多个 @Role,反射中用 getAnnotationsByType(Role.class) 获取全部。

















