String s = new String("abc"); // 創建 2 個 String 物件
"abc" 放入常量池(.class 檔常量表 → 運行時常量池)new String() 複製常量池內容到堆建立新物件
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); // true:同一常量池物件
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s3 == s4); // false:兩個堆物件
System.out.println(s3.equals(s4)); // true:內容相同
String s1 = new String("abc"); String s2 = new String("abc"); 創建幾個物件?三個:常量池 1 個 + 堆 2 個。
+ 其中一操作數為 StringtoString()StringBuilder 替換連續串接str = 1+2+str+3+4;
// 運行期等價於(編譯器優化後):
str = new StringBuilder()
.append(1+2) // 常量折疊:3
.append(str)
.append(3)
.append(4)
.toString();
// 創建物件:1 StringBuilder + 1 String 結果 + 可能 "3"/"4" 常量池物件
String s1 = "3jf34";
String s2 = "3" + "jf" + "3" + "4";
System.out.println(s1 == s2); // true:編譯期常量折疊,同一常量池物件
JLS 15.28:常量表達式編譯期計算,視為字面值。
str = str + "x" 是引用指向新物件,舊物件未變hashCode() 計算一次永久有效,Map 鍵高效| 代碼 | 物件數 | 解析 |
|---|---|---|
String s = "a" + "b" + "c"; | 1 | 編譯期常量折疊 |
String s = new String("abc"); | 2 | 常量池 + 堆 |
String s = new String("a") + new String("b"); | 4 | 2常量池 + 2堆 + 1結果(含Builder) |
String s = "ab"; String t = "a" + "b"; | 1 | 常量折疊同一物件 |
String s = "a"; String t = s + "b"; | 2 | 運行期 Builder 建立新物件 |
String s = "text"; 而非 new String("text")StringBuilderString 而非 StringBuilder(API 穩定性)== 比較引用,equals() 比較內容,intern() 手動入池String.intern() 濫用(永久代/Metaspace 壓力)掌握 String 物件創建機制、常量池與堆的交互、編譯器優化邊界、不可變性設計哲學,是寫出正確、高效 Java 代碼的基石。String 看似簡單,實則蘊含 JVM 核心記憶體管理智慧。