Java中的字符串只能位於內存中的兩個區域:常量池和Java堆。常量池維護了一個StringTable,它是一個hashtable,以字符串hashcode做爲鍵,字符串引用做爲值;Java堆中存儲的就是普通的字符串對象。 那麼如何判斷字符串到底位於哪個區域呢? 有如下幾種情形。java
String s="123";
複製代碼
虛擬機在處理字面量"123"時,首先在本地棧中建立字符串"123",隨後對其調用本地方法intern()。intern方法檢查StringTable中是否存在這個字符串,若是有則返回對其的引用;若是沒有,則將該字符串存入常量池中,並將其引用添加至StringTable中。 這裏值得注意的是,若是該字符串已經存儲於Java堆中,那麼intern方法將不會再將其拷貝至常量池中,而是直接將其引用添加至StringTable中。app
String s=new String("123");
複製代碼
"123"按照情形一處理,返回對常量池中字符串常量"123"的引用。隨後在Java堆中建立字符串對象,其內容與常量池中的"123"一致。優化
String s1=new String("123");
String s2=s1.intern();
複製代碼
第一行按照情形二處理。通過情形二,將產生一個對象和一個常量。而s2將引用常量池中的字面量"123"。爲了驗證這一說法,進行以下實驗:ui
String s1 = "123";
String s2 = s1.intern();
System.out.println(s1 == s2); // true
複製代碼
String s1 = new String("123");
String s2 = s1.intern();
System.out.println(s1 == s2); // false
複製代碼
實驗結果證實了咱們的說法。spa
String s=new String("1")+new String("23");
複製代碼
上述狀況等價於如下代碼:code
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append("1").append("23");
String s=stringBuilder.toString();
複製代碼
因爲編譯器的優化,將字符串拼接轉換爲StringBuilder操做。最後在Java堆中建立字符串對象。 最後看兩個例子:對象
String h = new String("12") + new String("3");
String h1 = new String("1") + new String("23");
String h3 = h.intern();
String h4 = h1.intern();
String h2 = "123";
System.out.println(h == h1); // false
System.out.println(h3 == h4); // true
System.out.println(h == h3); // true
System.out.println(h3 == h2); // true
複製代碼
String h = new String("12") + new String("3");
String h1 = new String("1") + new String("23");
String h2 = "123";
String h3 = h.intern();
String h4 = h1.intern();
System.out.println(h == h1); // false
System.out.println(h3 == h4); // true
System.out.println(h == h3); // false
System.out.println(h3 == h2); // true
複製代碼
來源:java兩個字符串對象相加和字符串字面量比較? - 海納的回答 - 知乎 www.zhihu.com/question/26…內存