Java中 String、StringBuffer、StringBuilder 的区别详解

在 Java 开发中,字符串处理是非常常见的操作。很多初学者会疑惑:为什么有了 String,还需要 StringBuffer 和 StringBuilder?它们之间到底有什么区别?

本篇博客将从底层原理、线程安全、性能、使用场景几个方面详细分析三者的区别。


一、String、StringBuffer、StringBuilder 简介

Java 中提供了三个主要用于处理字符串的类:

类 特点 是否可变 线程安全 性能
String 不可变字符串 ❌ 不可变 ✅ 安全 较低
StringBuffer 可变字符串 ✅ 可变 ✅ 安全 中等
StringBuilder 可变字符串 ✅ 可变 ❌ 不安全 最高

简单理解:

  • String:适合少量、不频繁修改的字符串

  • StringBuffer:适合多线程环境下频繁修改字符串

  • StringBuilder:适合单线程环境下频繁修改字符串


二、String 为什么不可变?

1. String 的本质

在 Java 中:

复制代码
String str = "hello";

实际上创建了一个 String 对象。

String 内部使用字符数组保存内容:

复制代码
private final char[] value;

例如:

复制代码
String对象

+-------------+
| hello       |
+-------------+
      |
      ↓
 ['h','e','l','l','o']

由于 String 被设计为不可变:

复制代码
String str = "hello";

str = str + " world";

看起来修改了字符串:

复制代码
hello
↓
hello world

实际上:

复制代码
原对象:

hello

新创建对象:

hello world

原来的字符串没有改变。


2. String 修改为什么性能低?

例如:

复制代码
String s = "";

for(int i=0;i<10000;i++){
    s += i;
}

执行过程:

第一次:

复制代码
""
+
"0"

创建新对象:

"0"

第二次:

复制代码
"0"
+
"1"

创建新对象:

"01"

第三次:

复制代码
"01"
+
"2"

创建新对象:

"012"

不断创建新的 String 对象。

所以:

大量字符串拼接时,不推荐使用 String。


三、StringBuffer 原理

StringBuffer 是可变字符串。

例如:

复制代码
StringBuffer sb = new StringBuffer();

sb.append("hello");

sb.append(" world");

内部:

第一次:

复制代码
hello

第二次:

复制代码
hello world

它修改的是原来的字符数组:

复制代码
StringBuffer对象

+----------------+
| hello world    |
+----------------+
        |
        ↓
 ['h','e','l','l','o',' ','w','o','r','l','d']

不会频繁创建对象。


四、StringBuilder 原理

StringBuilder 和 StringBuffer 几乎一样。

例如:

复制代码
StringBuilder sb = new StringBuilder();

sb.append("Java");

sb.append("开发");

内部也是维护一个可变数组。

区别:

StringBuffer 方法加了 synchronized 关键字,而 StringBuilder 没有。


五、线程安全区别

1. String

String 不可变:

复制代码
String s="hello";

多个线程同时访问:

复制代码
线程A --> hello
线程B --> hello
线程C --> hello

不会修改,所以安全。


2. StringBuffer

StringBuffer:

复制代码
public synchronized StringBuffer append(String str)
{
}

方法使用 synchronized:

复制代码
线程A
 |
锁
 |
修改StringBuffer


线程B
等待

所以:

✅ 线程安全

但是:

因为加锁:

性能降低。


3. StringBuilder

StringBuilder:

复制代码
public StringBuilder append(String str)
{
}

没有锁。

多个线程:

复制代码
线程A 修改

线程B 同时修改

可能冲突

所以:

❌ 不保证线程安全。

但是速度最快。


六、性能测试对比

假设循环拼接 10 万次:

复制代码
for(int i=0;i<100000;i++){
    xxx.append(i);
}

大概性能:

类型 时间
String 最慢
StringBuffer 中等
StringBuilder 最快

原因:

String

每次创建新对象:

复制代码
对象1
对象2
对象3
对象4
...

StringBuffer

修改自身:

复制代码
对象

hello world

但是:

复制代码
加锁
解锁

消耗性能。


StringBuilder

修改自身:

复制代码
hello world

没有锁。

所以最快。


七、三者使用场景

1. String 使用场景

适合:

固定字符串

例如:

复制代码
String name="Tom";

配置文件

复制代码
String url="https://www.baidu.com";

少量拼接

复制代码
String msg="hello"+"world";

2. StringBuilder 使用场景(推荐)

大部分开发场景首选:

例如:

生成 SQL:

复制代码
StringBuilder sql=new StringBuilder();

sql.append("select * ");

sql.append("from user");

生成 JSON:

复制代码
StringBuilder json=new StringBuilder();

json.append("{");

json.append("\"name\":\"Tom\"");

json.append("}");

特点:

  • 单线程

  • 大量拼接

  • 追求性能


3. StringBuffer 使用场景

现在使用较少。

主要用于:

多线程共享字符串。

例如:

多个线程写日志:

复制代码
线程1 ----\
           \
线程2 ---- StringBuffer
           /
线程3 ----/

保证数据安全。


八、StringBuffer 和 StringBuilder 源码区别

StringBuffer

复制代码
public synchronized StringBuffer append(String str)
{
    super.append(str);
    return this;
}

关键:

复制代码
synchronized

StringBuilder

复制代码
public StringBuilder append(String str)
{
    super.append(str);
    return this;
}

没有锁。


九、面试高频问题

1. String 为什么不可变?

答案:

因为 String 类设计为 final,并且内部 char 数组不可修改。

好处:

  1. 安全性高

  2. 支持字符串常量池

  3. 可以作为 HashMap 的 key

  4. 多线程访问安全


2. String、StringBuffer、StringBuilder区别?

标准回答:

String 是不可变字符串,每次修改都会创建新的对象;StringBuffer 和 StringBuilder 都是可变字符串,通过修改自身内容提高效率。StringBuffer 使用 synchronized 保证线程安全,因此性能低于 StringBuilder;StringBuilder 不保证线程安全,但是性能最高,适合单线程大量字符串操作。


3. 为什么 StringBuilder 比 StringBuffer 快?

因为:

复制代码
StringBuffer:
修改 + 加锁

StringBuilder:
修改

少了 synchronized 的开销。


十、总结

一句话记忆:

少量字符串 → String,大量拼接 → StringBuilder,多线程共享修改 → StringBuffer。

实际开发选择:

复制代码
普通业务代码
        |
        ↓
StringBuilder


多线程环境
        |
        ↓
StringBuffer


固定文本
        |
        ↓
String

在现在 Java 开发中:

StringBuilder 使用频率最高,StringBuffer 已经较少使用。

相关推荐
默_笙3 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
qq_426003963 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
长沙三为智能科技3 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
伞伞悦读3 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
只睡四小时3 天前
Canvas 弹道联机实战:700 行 + 固定时间步长
python·websocket·html5·游戏开发·canvas
C语言小火车3 天前
C/C++ 为什么需要编译器?
开发语言·c++
奇思妙想聪明勤奋的小羊3 天前
DeepAgents第5章:子Agent 与上下文隔离—让 Agent学会委派
人工智能·python·学习·语言模型
lpfasd1233 天前
2026年第38周GitHub趋势周报
python·科技·github