String、StringBuffer、StringBuilder 這三個(gè)類是 Java 字符串處理的核心類,本質(zhì)區(qū)別:String 不可變,StringBuffer/StringBuilder 可變,底層源碼圍繞「字符數(shù)組存儲(chǔ)」「不可變/可變?cè)O(shè)計(jì)」「線程安全」三大核心實(shí)現(xiàn)。
一、核心前置知識(shí)
- 底層存儲(chǔ):三者底層都是char[] 數(shù)組(JDK 9+ 優(yōu)化為 byte[] + coder,減少內(nèi)存占用,邏輯一致);
-
不可變 vs 可變:
- String:字符數(shù)組被
final修飾,無法修改數(shù)組內(nèi)容和引用; - StringBuffer/StringBuilder:繼承自
AbstractStringBuilder,字符數(shù)組無 final 修飾,支持動(dòng)態(tài)擴(kuò)容和修改;
- String:字符數(shù)組被
-
線程安全:StringBuffer 方法加了
synchronized鎖,線程安全;StringBuilder 無鎖,線程不安全。
二、String 源碼解析(不可變字符串)
1. 核心成員變量
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
// 核心:被 final 修飾的 char 數(shù)組 → 字符串不可變的根本原因
private final char value[];
// 緩存哈希值,避免重復(fù)計(jì)算
private int hash;
}
-
final class:String 類不能被繼承; -
final char value[]:數(shù)組引用不可變,數(shù)組內(nèi)容不可修改,任何字符串操作都會(huì)生成新對(duì)象。
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. 核心方法:拼接/修改(必生成新對(duì)象)
String 沒有任何修改原數(shù)組的方法,所有操作(substring/replace/+)都是新建 String 對(duì)象:
// substring 源碼:新建字符數(shù)組 → 新建 String 對(duì)象
public String substring(int beginIndex) {
// 邊界判斷...
return new String(value, beginIndex, subLen);
}
關(guān)鍵結(jié)論:頻繁字符串拼接(如循環(huán)中用 +),會(huì)創(chuàng)建大量臨時(shí)對(duì)象,性能極差。
4. 不可變的優(yōu)勢
- 線程安全(無需同步);
- 常量池緩存,節(jié)約內(nèi)存;
- 哈希值固定,適合作為 HashMap 鍵。
三、AbstractStringBuilder 源碼解析(父類,可變核心)
StringBuffer 和 StringBuilder 都繼承此類,90% 的方法(append/insert/delete)都在這個(gè)父類中實(shí)現(xiàn),是可變字符串的核心。
1. 核心成員變量
abstract class AbstractStringBuilder implements Appendable, CharSequence {
// 無 final 修飾 → 數(shù)組可修改、可擴(kuò)容
char[] value;
// 實(shí)際存儲(chǔ)的字符數(shù)量(不是數(shù)組長度)
int count;
}
-
count:有效字符長度,value.length是數(shù)組總?cè)萘浚A(yù)留擴(kuò)容空間)。
2. 動(dòng)態(tài)擴(kuò)容機(jī)制(核心)
所有追加操作都會(huì)先判斷容量,不足則自動(dòng)擴(kuò)容:
// 擴(kuò)容核心邏輯
private void ensureCapacityInternal(int minimumCapacity) {
// 所需容量 > 當(dāng)前數(shù)組長度 → 擴(kuò)容
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; - 傳入字符串時(shí):容量 = 字符串長度 + 16。
3. 核心方法:append(可變的關(guān)鍵)
直接在原數(shù)組追加字符,不創(chuàng)建新對(duì)象:
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
// 擴(kuò)容判斷
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. 核心:線程安全實(shí)現(xiàn)
所有對(duì)外方法都加了 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. 特點(diǎn)
- 線程安全,多線程環(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. 特點(diǎn)
- 無線程安全保障,單線程專用;
- 無鎖開銷,速度最快,是單線程字符串拼接首選。
六、三者核心源碼對(duì)比總結(jié)
| 特性 | String | StringBuffer | StringBuilder |
|---|---|---|---|
| 底層存儲(chǔ) | final char[](不可變) | char[](可變,繼承父類) | char[](可變,繼承父類) |
| 可變性 | 不可變,操作生成新對(duì)象 | 可變,直接修改原數(shù)組 | 可變,直接修改原數(shù)組 |
| 線程安全 | 安全(不可變) | 安全(synchronized 鎖) | 不安全 |
| 性能 | 最差(頻繁拼接產(chǎn)生垃圾對(duì)象) | 中等(加鎖開銷) | 最快(無鎖) |
| 使用場景 | 少量字符串、常量、多線程 | 多線程環(huán)境下頻繁拼接 | 單線程環(huán)境下頻繁拼接 |
總結(jié)
-
String:不可變,底層
final char[],適合少量、不變的字符串; - AbstractStringBuilder:父類,實(shí)現(xiàn)可變核心和動(dòng)態(tài)擴(kuò)容;
- StringBuffer:線程安全,加同步鎖,多線程拼接用;
- StringBuilder:非線程安全,無鎖,單線程拼接首選。