| 特性 | String | StringBuffer |
|---|---|---|
| 可變性 | 不可變(final 類別) | 可變(線程安全) |
| 連接操作 | 每次產生新物件 | 內部緩衝區擴展,避免新建 |
| 執行緒安全 | 不可變天生安全 | 方法加 synchronized |
| 效能(大量連接) | 極差,O(n²) 字元複製 | 優異,摊銷 O(1) |
| 適用場景 | 常量、少量連接、多執行緒共享 | 大量字串構建、單執行緒首選 StringBuilder |
str += "abc" 編譯器實際轉換為:
StringBuilder sb = new StringBuilder(str);
sb.append("abc");
str = sb.toString();
每次連接都建立新 StringBuilder、複製字元陣列、產生新 String,舊物件變垃圾需 GC。循環 5000 次連接 26 字母,String 耗時 ~46 秒,StringBuffer 僅 ~16 毫秒(差距超過 2000 倍)。
public class StringPerfTest {
public static void main(String[] args) {
String base = "abcdefghijklmnopqrstuvwxyz";
int times = 5000;
long t1 = System.currentTimeMillis();
String s = "";
for (int i = 0; i < times; i++) s += base;
System.out.println("String += : " + (System.currentTimeMillis() - t1) + " ms");
long t2 = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < times; i++) sb.append(base);
System.out.println("StringBuffer.append: " + (System.currentTimeMillis() - t2) + " ms");
}
}
典型輸出:
String += : 46000 ms
StringBuffer.append: 16 ms
StringBuffer 相同,但非線程安全(無 synchronized)。+ 操作符時實際使用 StringBuilder。// 使用 String 累積(極慢,記憶體暴增)
String content = "";
while ((len = in.read(buf)) != -1) content += new String(buf, 0, len);
// 使用 StringBuffer(快,記憶體穩定)
StringBuffer sb = new StringBuffer();
while ((len = in.read(buf)) != -1) sb.append(new String(buf, 0, len));
writer.write(sb.toString().toCharArray());
StringBuilder sb = new StringBuilder(); sb.append(...); String result = sb.toString();StringBuffer 或 ThreadLocal。String,編譯期常量摺疊自動優化。String.format()、MessageFormat、StringBuilder 組合。StringBuilder 或 Collectors.joining() (Stream API)。