字串操作是 Java 開發高頻場景,理解三者機制差異能避免效能陷阱。本文從不可變性、執行緒安全、效能基準三個維度深度對比。
| 特性 | String | StringBuffer | StringBuilder |
|---|---|---|---|
| 可變性 | 不可變 | 可變 | 可變 |
| 執行緒安全 | 天然安全(不可變) | 同步方法,安全 | 非同步,不安全 |
| 效能 | 頻繁修改極差 | 中等(鎖開銷) | 最佳(無鎖) |
| 繼承關係 | final class | extends AbstractStringBuilder | extends AbstractStringBuilder |
| JDK 版本 | 1.0 | 1.0 | 1.5 |
final char[] value(JDK 9+ 改為 byte[] + coder)。任何修改(concat、replace、substring)都會建立新物件、複製陣列。AbstractStringBuilder,內部維護可擴容 char[]/byte[],append/insert/delete 直接操作陣列,擴容時按 2 倍+2 複製。// String: ~5000ms (極慢,產生大量臨時物件觸發 GC)
String s = "";
for (int i = 0; i < 1_000_000; i++) s += "a";
// StringBuffer: ~15ms (同步鎖開銷)
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1_000_000; i++) sb.append("a");
// StringBuilder: ~5ms (最快)
StringBuilder sbl = new StringBuilder();
for (int i = 0; i < 1_000_000; i++) sbl.append("a");
結論: StringBuilder > StringBuffer > String(頻繁修改場景)。
StringStringBuilder(預設首選)StringBuffer(或 ThreadLocal 避免鎖)String.intern()、"literal" 自動入池。| 誤區 | 真相 |
|---|---|
| 編譯器會自動優化 + 為 StringBuilder | 僅單一表達式內(如 s = "a" + "b" + c),循環/多語句不會 |
| StringBuilder 非線程安全不可用 | 單執行緒或 ThreadLocal 範圍內完全安全且更快 |
| StringBuffer 已過時 | 未過時,多執行緒共享場景仍有價值 |
JDK 9 引入 Compact Strings:String 內部改為 byte[] + byte coder(LATIN1/UTF-16),純 ASCII 字串記憶體減半,StringBuilder/Buffer 同步更新。無需代碼變更即享受效能紅利。
選對工具,字串處理不再是效能黑洞。