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

相关推荐
XMXFS1 分钟前
小红书推荐算法底层逻辑解析:用数据思维做内容优化
python·算法·新媒体运营·推荐算法
hans7748829683 分钟前
仅根据BMI反推身高和体重?还真能做到!只需要简单的数论知识~
python·数学
释厄62334 分钟前
错误无误公理——错误正确本同源都迭代定律——逆转有价值
android·开发语言·kotlin
追光者4944 分钟前
我把 55 篇自动化日志翻了一遍:最容易出事的是这 4 个地方
python·自动化运维
2601_962885721 小时前
如何用 Python计算 CR能量指标(中间意愿指标)?
开发语言·python
打工仔折腾 AI1 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
hhb_6181 小时前
Flask+SQLite实现用户管理接口
python·sqlite·flask
全栈练习生1 小时前
RAG 准确率保障的体系化方案
python·ai
秋秋小事1 小时前
python 基础知识总结(一)
python
临床数据科学和人工智能兴趣组1 小时前
在R语言的生态系统中,字符串处理一直是一个重要且复杂的任务
开发语言·正则表达式·r语言·r语言-4.2.1