StringBuilder 与 StringBuffer的区别

一、线程安全

StringBuilder线程不安全的,StringBuffer线程安全

StringBuffer(线程安全)

java 复制代码
public class StringBuffer extends AbstractStringBuilder {
    
    // 所有修改方法都加 synchronized 锁
    public synchronized StringBuffer append(String str) {
        super.append(str);
        return this;
    }
    
    public synchronized int length() {
        return count;
    }
    
    public synchronized void setCharAt(int index, char ch) {
        // ...
    }
}

StringBuilder(非线程安全)

scala 复制代码
public class StringBuilder extends AbstractStringBuilder {
    
    // 无 synchronized 修饰
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
    
    public int length() {
        return count;
    }
}

二、继承关系

dart 复制代码
java.lang.Object
2    └── java.lang.AbstractStringBuilder
3            ├── java.lang.StringBuilder
4            └── java.lang.StringBuffer

两者都继承自 AbstractStringBuilder,共享大部分底层实现代码

三、核心字段(AbstractStringBuilder)

java 复制代码
abstract class AbstractStringBuilder implements Appendable, CharSequence {
2    // 存储字符的数组
3    char[] value;
4    
5    // 当前已使用的字符数量
6    int count;
7    
8    // ...其他方法
9}

注意 :JDK 9+ 之后,String 改用 byte[] + 编码标记(Compact Strings),但 StringBuilder/StringBuffer 仍主要使用 char[]

四、扩容机制(核心原理)

scss 复制代码
// AbstractStringBuilder 中的扩容逻辑
private void expandCapacity(int minimumCapacity) {
    // 新容量 = 原容量 × 2 + 2
    int newCapacity = (value.length + 1) * 2;
    
    // 如果新容量仍不够,则使用最小需求容量
    if (newCapacity < minimumCapacity) {
        newCapacity = minimumCapacity;
    }
    
    // 处理溢出情况
    if (newCapacity < 0) {
        if (minimumCapacity < 0) {
            throw new OutOfMemoryError();
        }
        newCapacity = Integer.MAX_VALUE;
    }
    
    // 创建新数组并复制
    value = Arrays.copyOf(value, newCapacity);
}

扩容规则

场景

扩容策略

默认构造

初始容量 16

容量不足

newCapacity = (oldCapacity + 1) * 2

指定容量构造

初始容量 = 指定值

五、性能对比测试

操作

String

StringBuffer

StringBuilder

10万次拼接

~3000-5000ms

~15-30ms

~10-20ms

原因

每次创建新对象

同步锁开销

无锁开销

六、源码核心差异总结

维度

StringBuffer

StringBuilder

类修饰

final class

final class

继承

AbstractStringBuilder

AbstractStringBuilder

方法修饰

synchronized

无同步

底层数组

char[] value

char[] value

扩容公式

(oldCapacity + 1) * 2

(oldCapacity + 1) * 2

默认容量

16

16

序列化

实现 Serializable

实现 Serializable

七、深度理解

  1. 为什么不安全?

    • StringBuilder 的 countvalue 在多线程下可能被同时修改,导致数据不一致
  2. 为什么性能好?

    • 避免了 synchronized 的锁竞争和上下文切换开销
  3. 最佳实践

    go 复制代码
    // ✅ 推荐:预估容量,减少扩容
    StringBuilder sb = new StringBuilder(256);
    
    // ✅ 推荐:链式调用
    sb.append("Hello").append(" ").append("World");
    
    // ❌ 避免:频繁扩容
    StringBuilder sb = new StringBuilder(); // 会多次扩容
相关推荐
ZC跨境爬虫3 分钟前
Playwright进阶操作:鼠标拖拽与各类点击实战(含自定义拖拽实例)
前端·爬虫·python·ui
小江的记录本6 分钟前
【RabbitMQ】RabbitMQ核心知识体系全解(5大核心模块:Exchange类型、消息确认机制、死信队列、延迟队列、镜像队列)
java·前端·分布式·后端·spring·rabbitmq·mvc
心静财富之门7 分钟前
《前端零基础入门:HTML + CSS + JavaScript 全套速查表(详细版 + 实例)》
前端·javascript·python
星空8 分钟前
前端--A_4--HTML表单
前端
!停12 分钟前
C++入门—内存管理
java·jvm·c++
海参崴-15 分钟前
C语言与C++语言发展历史详解
java·c语言·c++
无尽的罚坐人生18 分钟前
hot 100 146. LRU 缓存
java·开发语言·缓存
好家伙VCC19 分钟前
**发散创新:基于算子融合的深度学习推理优化实战**在现代AI部署场景
java·人工智能·python·深度学习
We་ct20 分钟前
JS手撕:DOM操作 & 浏览器API高频场景详解
开发语言·前端·javascript·面试·状态模式·操作·考点
wd5i8kA8i22 分钟前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
java·开发语言·php