Java中方法参数的类型注解必须声明为ElementType.TYPE_USE,才能通过Parameter.getAnnotatedType()正确读取;若声明为ElementType.PARAMETER,则仅出现在getAnnotations()中,与类型无关。

Java 中方法参数上的类型注解(Type Annotation),比如 @NonNull、@Positive 或自定义的 @MyTypeAnno,**必须声明为 ElementType.TYPE_USE**,才能通过 Parameter.getAnnotatedType() 正确读取。仅用 ElementType.PARAMETER 声明的注解,会出现在 Parameter.getAnnotations() 中,而不是类型上。
类型注解必须用 TYPE_USE 声明
这是最关键的前置条件。例如:
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NonNull {}
如果写成 @Target(ElementType.PARAMETER),它就属于“参数级注解”,和类型无关,getAnnotatedType() 不会包含它。
注解要写在类型位置,而非参数名前
正确写法(作用于类型):
立即学习“Java免费学习笔记(深入)”;
void process(@NonNull String name, @Positive int id) { ... }
错误写法(看似一样,实则语义不同):
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
void process(String @NonNull name, int @Positive id) { ... } // ❌ 语法错误(除非用嵌套类型)
注意:@NonNull String 表示“非空的 String 类型”,注解修饰的是 String 这个类型;而 String @NonNull name 是非法的,因为 @NonNull 没有放在合法的类型使用位置(如泛型边界、数组维度、强制转换等)。标准参数类型注解就写在类型关键字前。
通过 getAnnotatedType() 获取并提取注解
Parameter.getAnnotatedType() 返回的是 AnnotatedType,需调用其 getAnnotations() 或 getAnnotation(Class<T>):
- 对于普通类型(如
@NonNull String),getAnnotatedType()返回AnnotatedType,调用.getAnnotation(NonNull.class)可直接获取 - 对于带泛型的类型(如
@NonNull List<@NonNull String>),需递归检查AnnotatedParameterizedType的原始类型和类型参数的AnnotatedType - 注意:
getAnnotatedType().getAnnotations()只返回该类型**顶层**的注解(即直接写在String上的@NonNull),不包括泛型参数内部的注解(需手动展开)
完整示例代码
假设定义了:
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface NotEmpty {}
void example(@NotEmpty String s, List<@NotEmpty String> list) {}
反射读取:
Method m = clazz.getDeclaredMethod("example", String.class, List.class);
Parameter p0 = m.getParameters()[0];
AnnotatedType at0 = p0.getAnnotatedType(); // 对应 @NotEmpty String
NotEmpty anno0 = at0.getAnnotation(NotEmpty.class); // ✅ 可拿到
Parameter p1 = m.getParameters()[1];
AnnotatedType at1 = p1.getAnnotatedType(); // 对应 List<@NotEmpty String>
if (at1 instanceof AnnotatedParameterizedType apt) {
AnnotatedType[] typeArgs = apt.getAnnotatedActualTypeArguments();
if (typeArgs.length > 0) {
NotEmpty inner = typeArgs[0].getAnnotation(NotEmpty.class); // ✅ 拿到泛型里的 @NotEmpty
}
}
不复杂但容易忽略:类型注解生效的前提是声明位置 + 使用位置都符合 TYPE_USE 规范,缺一不可。

















