default 是编译期确定的固定值,必须是字面量或枚举常量等可在编译阶段求值的表达式,不能是变量、方法调用或 null(Class 类型除外);value 属性设 default 可支持省略写法;多属性设合理默认值可降低使用负担;反射调用时自动返回 default 值,无需判空。

default 是编译期确定的固定值,不是运行时逻辑
注解的 default 关键字声明的是一个编译期常量,必须是字面量或枚举常量等可在编译阶段求值的表达式。它不能是变量、方法调用、null(除 Class 类型可用 Void.class 等特殊形式外),也不能依赖 Spring 容器或配置文件。
例如合法写法:
String name() default "app";int timeout() default 5000;-
Level level() default Level.INFO;(Level 是枚举) -
Class> value() default Void.class;(模拟“无类”语义)
非法写法包括:String path() default System.getProperty("user.home"); 或 String desc() default null; —— 这两类都会导致编译失败。
value 属性默认化 + 省略写法,最常用简化路径
当注解只期望接收一个主要参数时,把该参数命名为 value 并设 default,能同时达成两个效果:外部使用时既可完全省略赋值,也可直接写值不带 key。
定义示例:
@interface Loggable {
String value() default "default-log";
}
使用方式对比:
-
@Loggable→ 自动取"default-log" -
@Loggable("order-service")→ 显式传参,value= 可省略 -
@Loggable(value = "order-service")→ 冗余写法,不推荐
这种设计让注解像“增强型标签”一样轻量,特别适合日志标识、权限码、路由前缀等高频单字段场景。
多属性协同设 default,降低调用方认知负担
真实业务注解往往不止一个字段。合理为非核心字段设默认值,能让调用方聚焦关键配置,避免每次都要填满所有项。
比如一个接口限流注解:
@interface RateLimiter {
String group() default "default"; // 分组名,多数场景用默认
int permitsPerSecond() default 100; // 每秒许可数,保守兜底
String fallback() default ""; // 降级方法名,默认不触发
}
此时使用者可以只写:@RateLimiter(permitsPerSecond = 200),其余自动补全;而不必强制写全三个字段。
注意原则:
- 默认值要有明确业务含义,比如
"default"比"unnamed"更易理解 - 数值类默认值应偏保守(如超时设 3000ms 而非 0)、字符串类默认值应具可读性
- 避免“空字符串”或“0”作为默认值,除非它在业务中真有明确语义
配合反射读取时,default 值天然可用,无需额外判空
通过 getAnnotation() 获取注解实例后,调用其方法(如 anno.value())会**自动返回 default 值**(如果调用方没显式赋值)。你不需要手动检查是否为 null 或做 fallback 判断。
例如:
@MyAnnotation
public class Service { }
// 反射获取
MyAnnotation anno = Service.class.getAnnotation(MyAnnotation.class);
System.out.println(anno.value()); // 直接输出 "unknown"(若 default 是 "unknown")
这使得处理器代码更简洁可靠——只要注解定义了 default,就一定能拿到有效值,消除了大量防御性判断。

















