java中无法通过parameterizedtype直接获取泛型实参上的类型注解,必须使用annotatedtype体系(如field.getannotatedtype()),再调用getannotatedactualtypearguments()等方法,并确保注解声明为@retention(runtime)和@target(type_use)。

Java 中通过 ParameterizedType 获取泛型类参数上的自定义类型注解,**不能直接获取**,因为类型注解(@Target(ElementType.TYPE_USE))在运行时默认不会被保留到 Class 或 Type 对象上 —— 它们需要显式保留在 TYPE_USE 位置,并通过 AnnotatedType 层级 API 访问。
必须用 AnnotatedType 替代 ParameterizedType
ParameterizedType 只描述「类型结构」(如 List<string></string>),不携带注解信息。要获取泛型实参上的类型注解(例如 List 中的 @NonNull),需使用 JDK 8+ 引入的 AnnotatedType 体系:
-
Field.getAnnotatedType()、Method.getAnnotatedReturnType()、Method.getAnnotatedParameterTypes()等返回的是AnnotatedType,而非原始Type - 若该
AnnotatedType是参数化类型(如@MyAnn List),可调用getAnnotatedActualTypeArguments()得到带注解的泛型实参数组 - 每个
AnnotatedType实例支持getAnnotationsByType(YourAnnotation.class)或getDeclaredAnnotations()
关键前提:注解必须声明为 @Retention(RetentionPolicy.RUNTIME) 且 @Target(TYPE_USE)
例如定义一个合法的类型注解:
// ✅ 正确:支持在类型使用处(如泛型参数)保留到运行时public @interface NonNull {
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE})
}
如果写成 @Target(ElementType.TYPE) 或没加 @Retention(RUNTIME),反射时一定拿不到。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
实际获取步骤(以字段为例)
假设你有如下类:
// 字段声明:List names;class Example {
List names;
}
反射获取 @NonNull 的代码如下:
- 通过
Field field = Example.class.getDeclaredField("names")获取字段 - 调用
AnnotatedType annotatedType = field.getAnnotatedType() - 确认它是参数化类型:
if (annotatedType instanceof AnnotatedParameterizedType) - 强转后获取泛型实参:
AnnotatedType[] args = ((AnnotatedParameterizedType) annotatedType).getAnnotatedActualTypeArguments() - 取第一个实参(即
@NonNull String):AnnotatedType arg0 = args[0] - 获取其上的注解:
NonNull nonNull = arg0.getAnnotation(NonNull.class)(或遍历所有注解)
注意边界情况
不是所有泛型位置都能拿到 AnnotatedType:
- 类定义本身的泛型(如
class Box)可通过Class.getAnnotatedSuperclass()或Class.getAnnotatedInterfaces()链式获取,但较复杂 - 方法返回值/参数中的嵌套泛型(如
Map>)需递归处理AnnotatedParameterizedType.getAnnotatedActualTypeArguments() - 数组类型注解(如
@NonNull String[])对应AnnotatedArrayType,需用getAnnotatedGenericComponentType() - 原始类型(
int)、通配符(?)、类型变量(T)也可能有AnnotatedType,但不一定含注解
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










