字串拼接是 Java 開發中最基礎也最容易踩坑的操作。本文從 String 不可變特性切入,透過位元碼反編譯揭示編譯器如何自動優化,並給出生產環境的最佳實踐指南。
String 物件一旦建立即不可變。所有拼接操作實質上都是建立新物件:
String s1 = "droidyue.com";
String s2 = s1; // 同一物件參考
String s3 = s1 + ".tw"; // 產生新物件,s1 不變
Java 禁止運算子多載,唯獨字串拼接的 +、+= 由編譯器特殊處理。
編譯期會將多字串拼接自動轉為 StringBuilder.append() 鏈式呼叫,再以 toString() 產出結果。
String info = userName + age + job;
反編譯位元碼等同於:
new StringBuilder()
.append(userName)
.append(age)
.append(job)
.toString();
零中間物件,效能無虞。
// 反模式:每次迴圈都 new StringBuilder
String result = "";
for (String v : values) {
result += v; // 每次迴圈隱式建立 StringBuilder
}
位元碼顯示 new StringBuilder 在迴圈內部,產生大量暫存物件,觸發頻繁 GC。
StringBuilder sb = new StringBuilder();
for (String v : values) {
sb.append(v);
}
String result = sb.toString();
位元碼證實 new StringBuilder 提升至迴圈外,僅建立一次物件。
| 場景 | 建議 |
|---|---|
| 少量字串單行拼接 | 直接用 +,可讀性最佳,編譯器會優化 |
| 已知總長度或大量拼接 | 預設容量 new StringBuilder(estimatedSize) |
| 多執行緒環境 | 改用 StringBuffer(同步化)或 ThreadLocal 隔離 |
| 日誌框架 | 使用佔位符 log.debug("user={}, id={}", name, id) 避免不必要拼接 |
理解編譯器如何將 + 轉為 StringBuilder,是寫出高效能 Java 代碼的關鍵。記住:迴圈外 new、迴圈內 append、最後 toString,這才是專業開發者的肌肉記憶。