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 已经较少使用。

相关推荐
金銀銅鐵1 小时前
[Python] 用 turtle 来绘制国际象棋棋盘(不含棋子)
python·游戏
這花開嗎1 小时前
2026年TTS文字转语音API哪家强?批量自动化配音成本与技术实测
python·flask·自动化
会周易的程序员1 小时前
js-shm: 高性能 Node.js 共享内存模块
开发语言·javascript·c++·node.js·共享内存·shm
笨蛋不要掉眼泪2 小时前
Java虚拟机:常用参数
java·开发语言·python
happy_0x3f2 小时前
前端应用的离线暂停更新策略
开发语言·前端·php
2501_909509102 小时前
DAY 31
python
李昊哲小课2 小时前
FastAPI 猫咖预约系统 API
人工智能·python·fastapi
shylyly_2 小时前
C++中的类型转换
开发语言·c++·匿名对象·隐式类型转换·拷贝优化
你驴我2 小时前
WhatsApp 消息撤回与编辑的幂等性设计实践
java·服务器·前端·后端·python