Java 中 String 物件是不可變的。每次使用 + 或 += 拼接,實際上都會產生新的 String 物件。若在迴圈中拼接大量字串,將產生大量中間物件,嚴重拖垮效能並增加 GC 壓力。
使用 javap -c 反編譯位元碼可發現:編譯器在編譯期會自動將多個常量或變數的連續拼接,優化為 StringBuilder.append() 鏈式呼叫,最後呼叫 toString()。例如:
String info = userName + age + job;
// 編譯器實際生成:
new StringBuilder().append(userName).append(age).append(job).toString();
此優化僅限於單一表達式內的拼接。
// 反模式:迴圈中隱式建立大量 StringBuilder
String result = "";
for (String val : values) {
result += val; // 每次迴圈都 new StringBuilder()!
}
反編譯顯示:new StringBuilder() 在迴圈內部,每次迭代皆建立新實例,效能極差。
// 正確姿勢:迴圈外建立,迴圈內複用
StringBuilder sb = new StringBuilder();
for (String val : values) {
sb.append(val);
}
String result = sb.toString();
位元碼證明:new StringBuilder() 提至迴圈外,僅建立一次物件。
| 場景 | 建議做法 | 原因 |
|---|---|---|
| 少量、固定次數拼接 | 直接用 + | 編譯器優化,程式碼可讀性最高 |
| 迴圈、大量、不定次數拼接 | 顯式 StringBuilder | 避免重複建立物件,效能提升數量級 |
| 多執行緒環境 | 使用 StringBuffer | 執行緒安全(同步開銷較大) |
理解編譯器優化的邊界,是寫出高效能 Java 程式碼的關鍵。記住:迴圈中拼接字串,務必顯式使用 StringBuilder。這不僅是效能優化,更是專業工程師的基本素養。