String s1 = "a";
s1 += "b"; // s1 現在指向堆中新對象 "ab"
System.out.println(s1 == "ab"); // false
棧: 堆: 常量池:
s1 ──────────────► 0x7F... "ab" (新對象) "ab" (常量池對象) ◄── 字面量 "ab"
// 內容比較
s1.equals("ab") // true (推薦)
"ab".equals(s1) // true (防 NPE 寫法)
Objects.equals(s1, "ab") // Java 7+ 工具類,雙向防 NPE
// 如果確定都是常量池對象(極少見)
s1.intern() == "ab" // 強制進常量池再比地址,不推薦
| 寫法 | 創建對象數 | 位置 | s == "a" |
|---|---|---|---|
| `String s = "a";` | 0 或 1 (常量池) | 常量池 | true |
| `String s = new String("a");` | 1 (堆) + 0/1 (常量池) | 堆 | false |
| `String s = "a" + "b";` | 1 (常量池, 編譯期優化) | 常量池 | true |
| `String s = "a"; s += "b";` | 1 (堆, 運行期) | 堆 | false |
永遠用 `equals()` 比較字符串內容,除非極其確定雙方都是常量池引用且需極致性能(極少見)。