編輯:我假設你知道你是比較引用,而不是字符串的內容。如果不是,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