编辑:我假设你知道你是比较引用,而不是字符串的内容。如果不是,s3.equals(s5)
是你正在寻找(如已经提到)。
s3
已被编译器优化为"hellohello1"
,它也被s4
重复使用。
我很惊讶编译器不够聪明,但是为
s5
做同样的事情。您使用的是哪个JDK版本?
。此优化仅适用于常量表达式(请参阅15.28 of Java Language Specification)。换句话说,对非最终变量的任何赋值都会拒绝以后优化的可能性。
这是的一个简单类的输出,它将您的代码封装到一个主要方法中(不是任何人要求它,但我很好奇自己)。让我们看看这是怎么回事:
public static void main(java.lang.String[]);
Code:
0: ldC#16; //String hello
2: astore_1
3: ldC#18; //String hello1
5: astore_2
6: ldC#20; //String hellohello1
8: astore_3
9: ldC#20; //String hellohello1
11: astore 4
13: new #22; //class java/lang/StringBuilder
16: dup
17: aload_1
18: invokestatic #24; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
21: invokespecial #30; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
24: aload_2
25: invokevirtual #33; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #37; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore 5
33: getstatic #41; //Field java/lang/System.out:Ljava/io/PrintStream;
36: aload_3
37: aload 4
39: if_acmpne 46
42: iconst_1
43: goto 47
46: iconst_0
47: invokevirtual #47; //Method java/io/PrintStream.println:(Z)V
50: getstatic #41; //Field java/lang/System.out:Ljava/io/PrintStream;
53: aload_3
54: aload 5
56: if_acmpne 63
59: iconst_1
60: goto 64
63: iconst_0
64: invokevirtual #47; //Method java/io/PrintStream.println:(Z)V
67: getstatic #41; //Field java/lang/System.out:Ljava/io/PrintStream;
70: aload 4
72: aload 5
74: if_acmpne 81
77: iconst_1
78: goto 82
81: iconst_0
82: invokevirtual #47; //Method java/io/PrintStream.println:(Z)V
85: return
LocalVariableTable:
Start Length Slot Name Signature
0 86 0 args [Ljava/lang/String;
3 83 1 s1 Ljava/lang/String;
6 80 2 s2 Ljava/lang/String;
9 77 3 s3 Ljava/lang/String;
13 73 4 s4 Ljava/lang/String;
33 53 5 s5 Ljava/lang/String;
}
我不是经验丰富的阅读字节码,但我给它一个去:)
- 以#开头的(例如#16)号码引用常量池。内容始终作为注释添加到该行中
ldC#16
后面跟着astore_1
表示“加载常量#16并将其存储在插槽1中”。正如你所看到的,在开始的时候,第一到第四的时隙会被转换为s1,s2,s3和s4(见LocalVariableTable)。
- 对于s5,没有详细描述,显然在将结果存储在时隙5(
astore 5
)之前涉及到StringBuilder并且加载了时隙1(aload_1
)和时隙2(aload_2
)。
此效应是由字符串interning引起的,在[本博客](http://javatechniques.com/blog/string-equality-and-interning/)中有深入解释。 – 2011-04-13 12:36:14