Java反射获取注解属性值需先通过getAnnotation()获取运行时代理对象,再直接调用value()等方法,JVM自动返回默认值或配置值,前提是注解Retention为RUNTIME。

Java中通过反射获取注解的属性值,比如 annotation.value(),核心在于先获取注解实例,再调用其方法。这不是直接“调用方法”,而是通过反射机制访问注解接口的默认方法(注解本质是接口),JVM会自动返回声明的默认值或实际配置值。
获取注解实例是前提
必须先通过反射拿到被标注元素(类、方法、字段等)上的注解对象,才能调用其属性方法:
- 使用
Class.getAnnotation(Class<T>)、Method.getAnnotation(...)等获取注解实例 - 返回的是运行时生成的代理对象(由
AnnotationParser创建),它实现了注解接口 - 调用
value()实际触发代理逻辑,返回配置值(若未显式设置,则返回@interface中定义的 default 值)
常见写法示例
以 Spring 的 @Value 或自定义注解为例:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Config {
String value() default "default";
}
在类中使用:
立即学习“Java免费学习笔记(深入)”;
public class AppConfig {
@Config("redis.timeout=5000")
private String config;
}
反射提取:
Field field = AppConfig.class.getDeclaredField("config");
Config annotation = field.getAnnotation(Config.class);
if (annotation != null) {
String val = annotation.value(); // ✅ 正确:直接调用,JVM自动处理
System.out.println(val); // 输出: redis.timeout=5000
}
注意类型匹配和空安全
注解属性返回值类型需与声明一致,且不能为 null(除非显式允许):
- 基本类型(
int、boolean)会返回默认值(如0、false),不会 NPE - 引用类型(
String、Class、枚举、数组)若未设置且无default,则返回null—— 调用前建议判空 - 数组类型用
String[] values(),直接调用即可,无需额外反射
进阶:动态读取多个属性或嵌套注解
如果注解有多个属性,可链式调用:
@MyAnnotation(key = "db.url", value = "jdbc:h2:mem:test")
public class DbConfig { }
提取时:
MyAnnotation ann = clazz.getAnnotation(MyAnnotation.class);
if (ann != null) {
String key = ann.key(); // 获取 key 属性
String val = ann.value(); // 获取 value 属性
}
嵌套注解(如 @Scope(value = "singleton"))也一样:先拿到外层注解,再调用其返回注解类型的属性方法。
不复杂但容易忽略细节:确保注解保留策略是 RetentionPolicy.RUNTIME,否则反射时拿不到;同时检查目标元素是否真被该注解标记。


















