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