StringBuilder 与 StringBuffer的区别
作者:互联网
2026-03-09
一、线程安全
StringBuilder线程不安全的,StringBuffer线程安全
StringBuffer(线程安全)
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(非线程安全)
public class StringBuilder extends AbstractStringBuilder {
// 无 synchronized 修饰
public StringBuilder append(String str) {
super.append(str);
return this;
}
public int length() {
return count;
}
}
二、继承关系
java.lang.Object
2 └── java.lang.AbstractStringBuilder
3 ├── java.lang.StringBuilder
4 └── java.lang.StringBuffer
两者都继承自 AbstractStringBuilder,共享大部分底层实现代码
三、核心字段(AbstractStringBuilder)
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[]
四、扩容机制(核心原理)
// 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
七、深度理解
-
为什么不安全?
- StringBuilder 的
count和value在多线程下可能被同时修改,导致数据不一致
- StringBuilder 的
-
为什么性能好?
- 避免了 synchronized 的锁竞争和上下文切换开销
-
最佳实践:
// 推荐:预估容量,减少扩容 StringBuilder sb = new StringBuilder(256); // 推荐:链式调用 sb.append("Hello").append(" ").append("World"); // 避免:频繁扩容 StringBuilder sb = new StringBuilder(); // 会多次扩容
相关推荐
专题
+ 收藏
+ 收藏
+ 收藏
+ 收藏
+ 收藏
最新数据
相关文章
快速搭建SpringBoot项目并整合MyBatis-Plus
Nacos双面超人:注册中心 + 配置中心,一个都不能少!
JVM 运行时数据区详解
2. Spring Boot 自动配置原理深度解析
[Java] Byte Buddy 和 InvocationHandler 的结合
java之线程池
14. MyBatis XML 热更新实战:告别重启烦恼
Tomcat 从陌生到熟悉
哇!绝了!原来这么简单!我的 Java 项目代码终于被 “拯救” 了!
Redis 缓存三大经典问题:穿透、击穿与雪崩
AI精选
