在 Java 中,String 是不可變對象。每次字串拼接、修改都會創建新的 String 實例,頻繁操作會產生大量臨時對象,增加 GC 壓力,降低性能。StringBuffer 作為可變字符序列,內部維護一個字符陣列,擴容機制靈活,非常適合頻繁修改字串的場景(且線程安全)。
| 類別 | 特點 | 適用場景 |
|---|---|---|
| Character | 單字符操作 | 字符判斷、轉換 |
| String | 不可變、最終類、常量池優化 | 字串常量、少量拼接、作為 Map Key |
| StringBuffer | 可變、線程安全、自動擴容 | 多線程環境下頻繁修改字串 |
| StringBuilder | 可變、非線程安全、性能略高 | 單線程環境下頻繁修改字串(推薦優先使用) |
StringBuffer sb = new StringBuffer("This is a StringBuffer");
int first = sb.indexOf("is"); // 2 - 首次出現位置
int firstFrom3 = sb.indexOf("is", 3); // 5 - 從索引 3 開始找
int last = sb.lastIndexOf("is"); // 17 - 最後一次出現位置
int lastBefore1 = sb.lastIndexOf("is", 1); // -1 - 索引 1 之前找不到
注意:參數為 String 而非 char,返回值為 int,找不到返回 -1。
StringBuffer sb = new StringBuffer("This is a StringBuffer");
String sub1 = sb.substring(4); // "is a StringBuffer" - 從索引 4 到結尾
String sub2 = sb.substring(4, 9); // "is a " - 索引 4 到 8(含頭不含尾)
返回 String,不影響原 StringBuffer 內容。
StringBuffer sb = new StringBuffer("Hello");
char lastChar = sb.charAt(sb.length() - 1); // 'o'
StringBuffer sb = new StringBuffer("Base: ");
sb.append(123); // 整數
sb.append(45.67); // 浮點數
sb.append(true); // 布爾值
sb.append('X'); // 字符
sb.append(new char[]{'A','B'}); // 字符陣列
sb.append("End"); // 字串
// 結果: "Base: 12345.67trueXABEnd"
支持所有基本類型及對象(調用 toString()),返回 this 支持鏈式調用。
StringBuffer sb = new StringBuffer("Hello World!");
sb.delete(5, 6); // 刪除索引 5 到 5(空格),結果 "HelloWorld!"
sb.deleteCharAt(sb.length() - 1); // 刪除最後一個字符 '!',結果 "HelloWorld"
StringBuffer sb = new StringBuffer("Hello");
sb.insert(2, 'W'); // "HeWllo"
sb.insert(3, new char[]{'A'}); // "HeWAWllo"
sb.insert(5, "Java"); // "HeWAWJava llo"
sb.insert(0, 100); // "100HeWAWJava llo"
第一個參數為偏移量(索引位置),支持所有類型。
StringBuffer sb = new StringBuffer("Hello World");
sb.replace(6, 11, "Java"); // 將索引 6-10 ("World") 替換為 "Java" -> "Hello Java"
三個參數:start(含)、end(不含)、replacement。與 String.replace() 完全不同。
StringBuffer sb = new StringBuffer("abcde");
sb.reverse(); // "edcba"
原地反轉,返回 this。
capacity():當前分配容量(默認 16,擴容策略:newCapacity = (oldCapacity + 1) * 2)。ensureCapacity(int minimumCapacity):確保最小容量,避免頻繁擴容。setLength(int newLength):強制設置長度,超出補 '\0',截斷則丟棄後續字符。new StringBuffer(1024) 減少擴容開銷。StringBuilder,避免同步鎖開銷。toString() 創建新 String,後續再 append 需重新創建 StringBuffer。CharArrayWriter 或分批寫入流。// 陷阱 1: 參數為 null 會追加 "null" 字串
StringBuffer sb = new StringBuffer();
sb.append(null); // 內容變為 "null"
// 陷阱 2: delete/replace 索引越界拋 StringIndexOutOfBoundsException
sb.delete(0, 100); // 如果長度不足會拋異常
// 陷阱 3: 線程安全不代表複合操作原子
// sb.append("a").append("b") 是原子的,但:
if (sb.length() > 0) sb.deleteCharAt(0); // 多線程下 length 和 delete 非原子,需外部同步
StringBuffer 是 Java 早期解決字串修改性能問題的核心工具,掌握其 API 細節(特別是 replace、insert 的索引語義)對維護老代碼至關重要。新代碼中單線程場景請優先選用 StringBuilder,多線程共享緩衝區才用 StringBuffer。