String、StringBuffer、StringBuilder 源碼解析

String、StringBuffer、StringBuilder 這三個類是 Java 字符串處理的核心類,本質(zhì)區(qū)別:String 不可變,StringBuffer/StringBuilder 可變,底層源碼圍繞「字符數(shù)組存儲」「不可變/可變設(shè)計」「線程安全」三大核心實現(xiàn)。

一、核心前置知識

  1. 底層存儲:三者底層都是char[] 數(shù)組(JDK 9+ 優(yōu)化為 byte[] + coder,減少內(nèi)存占用,邏輯一致);
  2. 不可變 vs 可變
    • String:字符數(shù)組被 final 修飾,無法修改數(shù)組內(nèi)容和引用
    • StringBuffer/StringBuilder:繼承自 AbstractStringBuilder,字符數(shù)組無 final 修飾,支持動態(tài)擴容和修改;
  3. 線程安全:StringBuffer 方法加了 synchronized 鎖,線程安全;StringBuilder 無鎖,線程不安全。

二、String 源碼解析(不可變字符串)

1. 核心成員變量

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    // 核心:被 final 修飾的 char 數(shù)組 → 字符串不可變的根本原因
    private final char value[];
    // 緩存哈希值,避免重復(fù)計算
    private int hash; 
}
  • final class:String 類不能被繼承
  • final char value[]:數(shù)組引用不可變,數(shù)組內(nèi)容不可修改,任何字符串操作都會生成新對象。

2. 構(gòu)造方法(核心)

最常用的構(gòu)造器,直接復(fù)制字符數(shù)組,保證不可變:

public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}
  • 為什么用 Arrays.copyOf?防止外部修改傳入的數(shù)組,影響 String 內(nèi)部值。

3. 核心方法:拼接/修改(必生成新對象)

String 沒有任何修改原數(shù)組的方法,所有操作(substring/replace/+)都是新建 String 對象

// substring 源碼:新建字符數(shù)組 → 新建 String 對象
public String substring(int beginIndex) {
    // 邊界判斷...
    return new String(value, beginIndex, subLen);
}

關(guān)鍵結(jié)論:頻繁字符串拼接(如循環(huán)中用 +),會創(chuàng)建大量臨時對象,性能極差。

4. 不可變的優(yōu)勢

  1. 線程安全(無需同步);
  2. 常量池緩存,節(jié)約內(nèi)存;
  3. 哈希值固定,適合作為 HashMap 鍵。

三、AbstractStringBuilder 源碼解析(父類,可變核心)

StringBuffer 和 StringBuilder 都繼承此類,90% 的方法(append/insert/delete)都在這個父類中實現(xiàn),是可變字符串的核心。

1. 核心成員變量

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    // 無 final 修飾 → 數(shù)組可修改、可擴容
    char[] value;
    // 實際存儲的字符數(shù)量(不是數(shù)組長度)
    int count;
}
  • count:有效字符長度,value.length 是數(shù)組總?cè)萘浚A(yù)留擴容空間)。

2. 動態(tài)擴容機制(核心)

所有追加操作都會先判斷容量,不足則自動擴容:

// 擴容核心邏輯
private void ensureCapacityInternal(int minimumCapacity) {
    // 所需容量 > 當(dāng)前數(shù)組長度 → 擴容
    if (minimumCapacity - value.length > 0) {
        // 新容量 = 原容量*2 + 2
        int newCapacity = value.length * 2 + 2;
        // 防止溢出,取最大值
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
        // 復(fù)制數(shù)組到新容量
        value = Arrays.copyOf(value, newCapacity);
    }
}
  • 默認(rèn)初始容量:16;
  • 傳入字符串時:容量 = 字符串長度 + 16。

3. 核心方法:append(可變的關(guān)鍵)

直接在原數(shù)組追加字符,不創(chuàng)建新對象

public AbstractStringBuilder append(String str) {
    if (str == null) str = "null";
    int len = str.length();
    // 擴容判斷
    ensureCapacityInternal(count + len);
    // 直接復(fù)制到原數(shù)組,修改 count
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

關(guān)鍵:返回 this,支持鏈?zhǔn)秸{(diào)用(append().append())。

四、StringBuffer 源碼解析(線程安全可變字符串)

1. 類定義

public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

直接繼承 AbstractStringBuilder,復(fù)用所有可變方法。

2. 核心:線程安全實現(xiàn)

所有對外方法都加了 synchronized 同步鎖

// append 方法:加鎖
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

// 其他方法:length()/delete()/insert() 都加鎖
public synchronized int length() {
    return count;
}

3. 特點

  • 線程安全,多線程環(huán)境下安全;
  • 加鎖有性能開銷,速度慢于 StringBuilder。

五、StringBuilder 源碼解析(非線程安全可變字符串)

1. 類定義

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

和 StringBuffer 完全一致,唯一區(qū)別:無同步鎖。

2. 核心方法

直接復(fù)用父類方法,沒有任何 synchronized 修飾

public StringBuilder append(String str) {
    super.append(str);
    return this;
}

3. 特點

  • 無線程安全保障,單線程專用;
  • 無鎖開銷,速度最快,是單線程字符串拼接首選。

六、三者核心源碼對比總結(jié)

特性 String StringBuffer StringBuilder
底層存儲 final char[](不可變) char[](可變,繼承父類) char[](可變,繼承父類)
可變性 不可變,操作生成新對象 可變,直接修改原數(shù)組 可變,直接修改原數(shù)組
線程安全 安全(不可變) 安全(synchronized 鎖) 不安全
性能 最差(頻繁拼接產(chǎn)生垃圾對象) 中等(加鎖開銷) 最快(無鎖)
使用場景 少量字符串、常量、多線程 多線程環(huán)境下頻繁拼接 單線程環(huán)境下頻繁拼接

總結(jié)

  1. String:不可變,底層 final char[],適合少量、不變的字符串;
  2. AbstractStringBuilder:父類,實現(xiàn)可變核心和動態(tài)擴容;
  3. StringBuffer:線程安全,加同步鎖,多線程拼接用;
  4. StringBuilder:非線程安全,無鎖,單線程拼接首選。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容