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(); // 会多次扩容
相关推荐
用户908324602731 小时前
Spring AI 1.1.2 集成 MCP(Model Context Protocol)实战:以 Tavily 搜索为例
java·后端
洋洋技术笔记1 小时前
vue3+vite+elementplus简单介绍
前端
Joker Zxc1 小时前
【前端基础(Javascript部分)】2、JavaScript的变量和数据类型
开发语言·前端·javascript
罗超驿1 小时前
JavaSE高频答疑:内部类同名变量访问全解 + Comparable与Comparator核心区别
java·开发语言·idea
yuki_uix1 小时前
别再死记优缺点了:聊聊 REST、GraphQL、WebSocket 的使用场景
前端
We་ct2 小时前
LeetCode 173. 二叉搜索树迭代器:BSTIterator类 实现与解析
前端·算法·leetcode·typescript
weixin_395448912 小时前
main.c_0222cursor
c语言·前端·算法
夕除2 小时前
js--23
java
无尽的沉默2 小时前
Thymeleaf 表达式
java·开发语言·前端