首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 字串處理三大核心類深度解析:String、StringBuffer、StringBuilder 差異與選型指南

     編輯:Java 相關知識

核心差異總覽表

特性StringStringBufferStringBuilder
可變性不可變可變可變
執行緒安全是(不可變天然安全)是(方法 synchronized)否
繼承體系final class繼承 AbstractStringBuilder繼承 AbstractStringBuilder
效能拼接產生新對象,較慢同步開銷,比 Builder 慢單執行緒最高效
適用場景常量、少量拼接、鍵值多執行緒共享緩衝區單執行緒大量拼接、構建字串
JDK 版本1.01.05.0

底層原理解析

String:不可變的字元陣列

public final class String {
    private final char value[]; // JDK 8
    // private final byte[] value; // JDK 9+ Compact Strings
    // ...
}
  • final 修飾陣列引用與類本身,保證不可變性。
  • 每次拼接 s1 + s2 編譯器轉為 new StringBuilder().append(s1).append(s2).toString()。
  • 字串常量池:字面量自動駐留,intern() 手動駐留。

StringBuffer / StringBuilder:共享 AbstractStringBuilder

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    char[] value; // 可變字元陣列
    int count;    // 實際長度

    // 擴容邏輯:新容量 = 舊容量 * 2 + 2
    void expandCapacity(int minimumCapacity) { ... }

    // 核心 append 邏輯
    public AbstractStringBuilder append(String str) {
        if (str == null) str = "null";
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
}

StringBuffer:同步包裝

public class StringBuffer extends AbstractStringBuilder {
    @Override
    public synchronized StringBuffer append(String str) {
        super.append(str);
        return this;
    }
    @Override
    public synchronized int indexOf(String str) {
        return super.indexOf(str, 0);
    }
    // 所有公共方法皆 synchronized
}

StringBuilder:無同步,JDK 5+ 引入

public class StringBuilder extends AbstractStringBuilder {
    // 繼承所有 append/insert/delete 等方法,無 synchronized
    // 單執行緒下效能優於 StringBuffer 約 10-15%
}

效能實測基準(JMH 參考)

@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class StringConcatBenchmark {
    @Benchmark
    public void stringConcat() {
        String s = "";
        for (int i = 0; i < 1000; i++) s += "x"; // 極差
    }

    @Benchmark
    public void stringBuffer() {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 1000; i++) sb.append("x");
    }

    @Benchmark
    public void stringBuilder() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1000; i++) sb.append("x");
    }
}

/* 典型結果(ops/ms,越高越好):
stringBuilder  >>  stringBuffer  >  stringConcat
單執行緒下 Builder 最快,Buffer 因同步略慢,String 拼接最差(O(n²) 對象產生)
*/

選型決策樹

需要共享給多執行緒?
├── 是 → StringBuffer(或 ThreadLocal + 最後合併)
└── 否 → 單執行緒大量拼接?
    ├── 是 → StringBuilder(預設容量 16,可預估大小 new StringBuilder(1024))
    └── 否 → 少量拼接/常量 → String(編譯器優化 + 常量池)

常見誤區與最佳實踐

誤區正確做法
迴圈中用 + 拼接改用 StringBuilder,或 Java 8+ Stream: list.stream().collect(Collectors.joining())
以為 StringBuffer 總是安全複合操作(如 if (sb.length() > 0) sb.deleteCharAt(...))仍需外部同步
預設容量導致頻繁擴容預估大概長度:new StringBuilder(estimatedSize)
用 StringBuilder 做 Map KeyStringBuilder 非不可變,不可作 Key;轉 String 後使用
JDK 9+ Compact Strings 未知Latin-1 字串改用 byte[] + coder,記憶體減半,String 效能提升

現代 Java 替代方案

  • String.join(delimiter, elements) (JDK 8+)
  • Collectors.joining() / Collectors.joining(delimiter, prefix, suffix)
  • String.format() / MessageFormat / StringBuilder 模板引擎
  • java.text.StringBuilder (JDK 11+ 新增 repeat(), strip() 等)

總結

  • String:不可變、執行緒安全、適合常量與少量操作。
  • StringBuffer:可變、執行緒安全(同步)、舊代碼遺留、多執行緒共享緩衝區。
  • StringBuilder:可變、非執行緒安全、單執行緒高效能首選、JDK 5+ 標準替代品。
  • 現代開發:單執行緒首選 StringBuilder,多執行緒用 ThreadLocal 或無鎖設計,極少直接用 StringBuffer。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved