为什么注释字符串值没有实现?

尽管重用了字符串常量和文字,但以下代码段打印出4个不同的哈希码。 为什么字符串值没有插入注释元素?

public class Foo { @Retention(RetentionPolicy.RUNTIME) @interface Bar { String CONSTANT = "foo"; String value() default CONSTANT; } public static void main(String[] args) throws Exception { System.out.println(System.identityHashCode(Bar.CONSTANT)); System.out.println(System.identityHashCode(Foo.class.getMethod("test1").getAnnotation(Bar.class).value())); System.out.println(System.identityHashCode(Foo.class.getMethod("test2").getAnnotation(Bar.class).value())); System.out.println(System.identityHashCode(Foo.class.getMethod("test3").getAnnotation(Bar.class).value())); } @Bar public void test1() {} @Bar("foo") public void test2() {} @Bar(Bar.CONSTANT) public void test3() {} } 

字符串文字是实际的,但注释需要解析,它们存储在字节数组中。 如果你看一下java.lang.reflect.Method类,你可以看到:

 private byte[] annotations; private byte[] parameterAnnotations; private byte[] annotationDefault; 

另请参阅同一类的public Object getDefaultValue() ,以了解如何调用AnnotationParser。 流程一直持续到这里AnnotationParser.parseConst并输入

 case 's': return constPool.getUTF8At(constIndex); 

ConstantPool.getUTF8At方法是本机方法的委托。 你可以在这里看到本机实现getUFT8At的代码。 解析的常量永远不会被实现,并且永远不会从StringTable(其中字符串被实现)中检索。

我认为这可能是实施的选择。 已经创建了Interning以在String literal之间进行更快速的比较,因此仅用于在方法实现中可用的实体文字。

这是因为您在运行时访问注释并符合java规范 – 例3.10.5-1。 String Literals ,字符串是新创建的,因此是不同的。

所有文字字符串和编译时字符串值常量表达式都会自动实现

在您的情况下, test1的值将在运行时从native value()方法计算(查看AnnotationDefault属性 )。

 String value() default CONSTANT; 

其他情况也将在运行时计算。

从注释中获取值时,必须明确地执行实习

 String poolString = Foo.class.getMethod("test1").getAnnotation(Bar.class).value().intern(); System.out.println(poolString == Bar.CONSTANT);