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),反射时一定拿不到。
立即学习“Java免费学习笔记(深入)”;
实际获取步骤(以字段为例)
假设你有如下类:
// 字段声明:List<@NonNull String> names;class Example {
List<@NonNull String> 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<@My T>)可通过Class.getAnnotatedSuperclass()或Class.getAnnotatedInterfaces()链式获取,但较复杂 - 方法返回值/参数中的嵌套泛型(如
Map<@Key String, @Value List<@Item Integer>>)需递归处理AnnotatedParameterizedType.getAnnotatedActualTypeArguments() - 数组类型注解(如
@NonNull String[])对应AnnotatedArrayType,需用getAnnotatedGenericComponentType() - 原始类型(
int)、通配符(?)、类型变量(T)也可能有AnnotatedType,但不一定含注解


















