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
相关产品推荐
相关产品推荐

