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

Java注解默认对象的System.identityHashCode为何不一致?

Java注解默认值的对象身份差异问题

问题说明

以下测试代码中,注解Test定义了静态常量name,并将其设为name()方法的默认值。但运行后发现,直接访问Test.name和调用注解实例的name()方法得到的对象,System.identityHashCode结果不同。

测试代码

import cn.hutool.core.util.ReflectUtil;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class Question {

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    @interface Test {

        String name = "123";

        String name() default name;

    }

    @Test
    private final String demo = null;

    public static void main(String[] args) {
        System.out.println(System.identityHashCode(Test.name));
        System.out.println(System.identityHashCode(
                ReflectUtil.getField(Question.class, "demo").getAnnotation(Test.class).name())
        );
    }
}

运行结果

1147985808
1789447862

原因解析

核心原因是注解默认值的返回逻辑与静态常量的引用逻辑完全独立:

  • 注解中的String name = "123"是public static final的静态常量,在Question$Test接口类加载时就会初始化,对应的String实例存入字符串常量池。
  • 通过反射获取的注解实例是JVM动态生成的代理对象,调用name()方法时,代理逻辑会读取编译时存储在注解元数据中的默认值,重新生成对应的String实例(而非直接引用Test.name的已有实例)。
  • 虽然两个String实例的内容完全一致(equals()返回true),但它们是内存中不同的对象,因此System.identityHashCode返回的哈希值不同。

可以通过以下代码验证这一点:

public static void main(String[] args) {
    Test annotation = ReflectUtil.getField(Question.class, "demo").getAnnotation(Test.class);
    System.out.println(Test.name.equals(annotation.name())); // 输出true
    System.out.println(Test.name == annotation.name()); // 输出false
}

内容的提问来源于stack exchange,提问作者Forever

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 07:54:22