为何Checker Framework注解无法被Field#getDeclaredAnnotations获取?
Checker Framework @Nullable注解无法通过反射获取的问题解析
我尝试扩展注解处理代码以支持Checker Framework的@Nullable注解,但一直不生效。检查后发现,即便该注解带有@Retention(RUNTIME)元注解,也无法通过反射获取到。
测试代码如下:
class AnnotationTest { @javax.annotation.Nullable Object javax; @jakarta.annotation.Nullable Object jakarta; @org.checkerframework.checker.nullness.qual.Nullable Object checker; @Test void annotations() { final Field[] fields = getClass().getDeclaredFields(); for (final Field field : fields) { System.out.println(field.getName() + " annotated with " + Arrays.toString(field.getDeclaredAnnotations())); } } }
输出结果:
javax annotated with [@javax.annotation.Nullable()] jakarta annotated with [@jakarta.annotation.Nullable()] checker annotated with []
这是一个Spring Boot项目,无论用IntelliJ还是Gradle执行测试,结果都一致。其他注解能正常获取,唯独Checker Framework的注解不行?
附上该注解的定义:
@SubtypeOf({}) @ImplicitFor(literals = LiteralKind.NULL, typeNames = java.lang.Void.class) @DefaultInUncheckedCodeFor({TypeUseLocation.RETURN, TypeUseLocation.UPPER_BOUND}) @Documented @Retention(RetentionPolicy.RUNTIME) // <-- 运行时保留! @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) public @interface Nullable {}
问题原因
核心差异在于注解的@Target定义:
javax.annotation.Nullable和jakarta.annotation.Nullable的@Target包含ElementType.FIELD,属于元素注解,直接标注在字段本身上,因此可以通过field.getDeclaredAnnotations()获取。- Checker Framework的
@Nullable的@Target仅包含ElementType.TYPE_USE和ElementType.TYPE_PARAMETER,属于类型注解,它标注的是字段的类型(即Object这个类型),而非字段元素本身。getDeclaredAnnotations()只能获取直接标注在字段上的注解,无法获取类型上的注解。
解决办法
要获取类型注解,需要使用Java反射API中的AnnotatedType相关方法,修改测试代码如下:
class AnnotationTest { @javax.annotation.Nullable Object javax; @jakarta.annotation.Nullable Object jakarta; @org.checkerframework.checker.nullness.qual.Nullable Object checker; @Test void annotations() { final Field[] fields = getClass().getDeclaredFields(); for (final Field field : fields) { // 获取字段的类型注解 Annotation[] typeAnnotations = field.getAnnotatedType().getAnnotations(); System.out.println(field.getName() + " type annotated with " + Arrays.toString(typeAnnotations)); // 同时保留字段本身的注解输出,对比差异 System.out.println(field.getName() + " field annotated with " + Arrays.toString(field.getDeclaredAnnotations())); } } }
修改后的输出会显示Checker Framework的@Nullable注解:
javax type annotated with [] javax field annotated with [@javax.annotation.Nullable()] jakarta type annotated with [] jakarta field annotated with [@jakarta.annotation.Nullable()] checker type annotated with [@org.checkerframework.checker.nullness.qual.Nullable()] checker field annotated with []
额外说明
类型注解是Java 8引入的特性,用于标注类型的使用场景(比如字段类型、方法返回值类型、参数类型等),而传统的元素注解是标注在类、字段、方法等元素上。如果你的注解处理逻辑需要支持类型注解,就需要调整反射获取方式,针对不同的注解类型选择对应的API。
内容的提问来源于stack exchange,提问作者knittl
相关产品推荐
相关产品推荐

