You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 21:46:11