2016-10-06 66 views
2

據我所知,字符串連接「+」操作符在Java中使用StringBuilder的,這樣的東西一樣實現:關於「+」操作符和StringBuilder的實施

String s = "foo" + "bar" 

內部編譯如下:

String s = new StringBuilder().append("foo").append("bar").toString(); 

所以,我想是這樣的:

String foo1 = "foobar"; 
String foo2 = new String("foobar"); 
String foo3 = "foo" + "bar"; 
char[] fooarray = {'f','o','o','b','a','r'}; 
String foo4 = new String(fooarray); 

接下來我測試這些針對彼此使用==運算符。結果大部分是我所期望的:foo2和foo4沒有爲其他字符串返回「==」。

但是,foo3 == foo1返回true。這是什麼原因? StringBuilder類的toString方法內部調用「new String」,所以foo3不應該是一個獨特的對象,就像foo2一樣?

+11

兩串的字符串連接*文字*由* *編譯完成,而不是在運行時。所以寫''foo「+」bar「'和寫foobar''是一樣的。它允許您將字符串文字分成多行,而不會影響性能。 – Andreas

+3

另外,如果你的字符串是'final',那麼即使在編譯時's s = s1 + s2'也會發生,如果s1和s2是引用字符串 – TheLostMind

回答

4

foo3 == foo1返回true的原因是因爲字符串池。

當您連接字符串文字(即使是final字符串不是文字)時,連接發生在編譯時,所以當程序執行值String foo1 = "foobar";String foo3 = "foobar";

字符串池或字符串表是存儲字符串引用的堆上的特殊區域。

現在,當您創建字符串foo1時,如果沒有其他字符串文字值爲foobar,它將保留在池中。但是在foo3的情況下,已經有一個值爲foobar的字符串文字,因此foo1foo3指向字符串池中的同一對象,這樣做是爲了節省內存。

當您使用new關鍵字創建字符串時,該對象駐留在堆上但位於字符串池之外。

如果您希望使用new關鍵字創建的字符串位於字符串池中(如果該池中已存在相同的值),則必須調用字符串intern()方法並將引用分配回String變量。

欲瞭解更多信息 - What is the Java string pool and how is 「s」 different from new String(「s」)?