field.getannotatedtype() 能获取泛型实参上的类型注解(如 @nonnull),而 getgenerictype() 会丢失这些注解;需通过 annotatedparameterizedtype 的 getannotatedactualtypearguments() 逐层解析并提取注解,且注解必须声明为 @target(type_use) 并保留策略为 runtime。

在 Java 中,Field.getAnnotatedType() 用于获取字段声明处的**完整带注解的类型信息**,包括泛型参数上的类型注解(如 @NonNull、@Nullable 等),而不仅仅是原始类型或擦除后的类型。它特别适用于处理像 List 这类在泛型实参上标注了注解的场景。
为什么 getAnnotatedType 比 getGenericType 更关键
getGenericType() 只返回类型结构(如 ParameterizedType),但会丢失泛型参数上的注解;而 getAnnotatedType() 返回的是 AnnotatedType 子类(如 AnnotatedParameterizedType),能逐层访问每个类型组件的注解。
- 例如字段声明为:
private List names; -
field.getGenericType()→ 得到List<string></string>(注解已丢失) -
field.getAnnotatedType()→ 得到可查询@NonNull的AnnotatedParameterizedType
获取泛型实参上的类型注解(核心步骤)
对一个带泛型的字段(如 Map),需向下解析 AnnotatedType 层级:
- 先调用
field.getAnnotatedType()得到顶层AnnotatedType - 若它是
AnnotatedParameterizedType,用getAnnotatedActualTypeArguments()获取每个泛型实参的带注解类型 - 对每个实参,调用
getAnnotations()或getAnnotation(Class<t>)</t>提取类型注解 - 若实参本身是嵌套泛型(如
List),可用getType()继续递归解析
实际代码示例
假设有一个类:
public class Example {private Map> data;
}
提取 String 上的 @NonNull 和内层 String 上的 @Email:
- 获取
data字段的AnnotatedType - 转型为
AnnotatedParameterizedType,调用getAnnotatedActualTypeArguments()→ 得到长度为 2 的数组 - 第一个元素对应
@NonNull String:其getAnnotations()包含@NonNull;getType()是String.class - 第二个元素是
AnnotatedParameterizedType(对应List),再对其调用getAnnotatedActualTypeArguments(),即可拿到@Email
注意事项与常见陷阱
类型注解必须用 @Target(ElementType.TYPE_USE) 声明,否则运行时不可见;编译需加 -parameters(对方法参数有用,但字段类型注解不依赖此);反射获取注解仅在保留策略为 RetentionPolicy.RUNTIME 时有效。
- 检查注解是否存在:用
annotatedType.isAnnotationPresent(NonNull.class) - 不要混淆
Field.getAnnotations()(字段自身注解)和getAnnotatedType().getAnnotations()(类型位置注解) - 数组类型、通配符(
? extends @NonNull T)、类型变量(T)也支持类型注解,解析方式类似但需对应不同AnnotatedType子类
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











