字串操作是 Java 開發高頻場景。String 不可變,StringBuffer 線程安全可變,StringBuilder 非線程安全可變。三者在效能、適用場景上有明顯差異,本文從原理、效能測試、最佳實踐三方面解析。
| 特性 | String | StringBuffer | StringBuilder |
|---|---|---|---|
| 可變性 | 不可變 | 可變 | 可變 |
| 線程安全 | 是(不可變天然安全) | 是(方法同步) | 否 |
| 底層結構 | char[] / byte[] (Java 9+) | char[] / byte[] | char[] / byte[] |
| 主要方法 | concat, substring... | append, insert... | append, insert... |
| 引入版本 | JDK 1.0 | JDK 1.0 | JDK 1.5 |
// 編譯期常量折疊,等同於 "This is only a simple test" String s1 = "This is only a" + " simple" + " test"; // 變數拼接:編譯器轉為 StringBuilder String s2 = "This is only a"; String s3 = " simple"; String s4 = " test"; String s5 = s2 + s3 + s4; // 實際用 StringBuilder 建構
結論:常量拼接零開銷;變數拼接編譯器自動優化為 StringBuilder,手動用 StringBuffer 反而較慢(同步開銷)。
// 糟糕:每次迴圈產生新 StringBuilder 並 toString() String result = ""; for (int i = 0; i < 10000; i++) result += i; // 良好:複用單一 StringBuilder StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10000; i++) sb.append(i); String result = sb.toString();
StringBuilder ≫ StringBuffer > String +=StringBuffer 安全但有鎖爭用;建議改用 ThreadLocal 或無鎖資料結構。StringBuffer 所有公開方法標記 synchronized。StringBuilder 繼承 AbstractStringBuilder,方法無同步。newCapacity = (oldCapacity << 1) + 2。byte[] + coder (Latin-1/UTF-16) 節省記憶體。StringBuilder(單執行緒、高效能)。StringBuffer 或 ThreadLocal。+ 或 String.concat,可讀性最高。String,內部構建用 StringBuilder。String 不可變適合作為不可變資料載體;StringBuilder 是高效能可變字串首選;StringBuffer 因同步開銷大,現代開發極少直接使用,除非確有多執行緒共享緩衝區需求且不願引入額外同步機制。