Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么注释默认字符串虽然必须是常量,但不相同_Java_String_Annotations_Identity_Java Annotations - Fatal编程技术网

Java 为什么注释默认字符串虽然必须是常量,但不相同

Java 为什么注释默认字符串虽然必须是常量,但不相同,java,string,annotations,identity,java-annotations,Java,String,Annotations,Identity,Java Annotations,我有一个粗略的想法,但仍然想问是否有人知道为什么作为注释默认值提供的String常量会更改标识,即使它们引用静态常量 为了说明,为什么此代码会打印true、true、false、false @TestAnn public class TestClass { public static final String STRING_CONSTANT = "SHOULD_BE_CONSTANT"; @Retention(RetentionPolicy.RUNTIME) publ

我有一个粗略的想法,但仍然想问是否有人知道为什么作为注释默认值提供的
String
常量会更改标识,即使它们引用静态常量

为了说明,为什么此代码会打印
true、true、false、false

@TestAnn
public class TestClass {

    public static final String STRING_CONSTANT = "SHOULD_BE_CONSTANT";

    @Retention(RetentionPolicy.RUNTIME)
    public @interface TestAnn {
        String value() default TestClass.STRING_CONSTANT;
    }
    public class OtherTestClass {
        String NOT_EVEN_STATIC = TestClass.STRING_CONSTANT;
    }
    private void run() throws Exception {

        System.out.println(STRING_CONSTANT == constantValue());

        System.out.println(STRING_CONSTANT == new OtherTestClass().NOT_EVEN_STATIC);

        String str1 = getClass().getAnnotation(TestAnn.class).value();
        System.out.println(STRING_CONSTANT == str1);

        String str2 = (String) TestAnn.class.getMethod("value").getDefaultValue();
        System.out.println(STRING_CONSTANT == str2);
    }
    private String constantValue() {
        return TestClass.STRING_CONSTANT;
    }
    public static void main(String[] args) throws Exception {
        new TestClass().run();
    }
}

棘手的是,当使用
value()
getDefaultValue()
时,使用基于其运行时类的反射检索实际值,基本上创建一个新的对象字符串对象(Type object)并用字符串值填充

因此,当您尝试使用==运算符来比较对象时,它将返回false,但equal将返回true,因为它比较内容

前两个示例返回true,因为您引用了相同的对象,
constantValue()
返回相同的对象,
甚至不存储相同的引用

您可以参考这一点来了解为什么总是带有常量值的字符串总是使用==相等,例如NOT_EVEN_静态示例


干杯

因为
字符串
中的值实际上不是intern
字符串
,让我们来查找注释中的
字符串
的位置

首先,我们检查
类中的代码,它是如何创建注释数据的

private AnnotationData createAnnotationData(int classRedefinedCount) {
    Map<Class<? extends Annotation>, Annotation> declaredAnnotations =
        AnnotationParser.parseAnnotations(getRawAnnotations(), getConstantPool(), this);
...
}
因此,
AnnotationParser
ConstantPool
获取
String
值。让我们自己获得价值:

Method m = Class.class.getDeclaredMethod("getConstantPool");
m.setAccessible(true);
ConstantPool pool = (ConstantPool) m.invoke(getClass());
然后获取
字符串
及其intern值,并进行比较:

String str = pool.getUTF8At(9); // I find the index by traverse the pool, may different in your code
String intern = str.intern();
System.out.println(str == intern); // false
System.out.println(str == STRING_CONSTANT); // false
System.out.println(intern == STRING_CONSTANT); // true
因此,
ConstantPool
中的
字符串
不是intern值。我在eclipse中检查了他们的id

str(id=371),实习生(id=372)

因此,事实是
ConstantPool
对常量字符串执行
intern
,但它返回它所持有的不是intern的原始值

String str = pool.getUTF8At(9); // I find the index by traverse the pool, may different in your code
String intern = str.intern();
System.out.println(str == intern); // false
System.out.println(str == STRING_CONSTANT); // false
System.out.println(intern == STRING_CONSTANT); // true