java基础String、Stringbuffer、StringBuilder

10 阅读2分钟

在 Java 中,StringStringBuffer 和 StringBuilder 都用于处理字符串,但它们在可变性、线程安全性、性能上有本质区别。下面从三个维度对比,并给出使用建议。


一、基本对比

特性StringStringBufferStringBuilder
可变性不可变可变可变
线程安全安全(不可变天然安全)安全(方法用 synchronized 修饰)不安全
性能拼接时会产生大量临时对象,效率低同步开销,比 StringBuilder 慢最快
引入版本JDK 1.0JDK 1.0JDK 1.5

二、详解

1. String:不可变字符序列

  • 一旦创建,其内容无法修改。任何“修改”操作(如 +concatsubstring)都会生成新的 String 对象。
  • 优点:线程安全、可缓存(如字符串常量池)、适合作为 HashMap 的键。
  • 缺点:频繁拼接时会产生大量中间对象,造成内存浪费和 GC 压力。

示例

java

String s = "Hello";
s += " World";  // 实际生成了新的 String 对象

2. StringBuffer:可变且线程安全

  • 内部维护一个可变的字符数组,提供 append()insert() 等方法修改内容。
  • 所有修改方法都加了 synchronized 关键字,保证多线程环境下安全。
  • 适用于多线程字符串操作场景(如日志记录、多线程拼接)。

示例

java

StringBuffer sb = new StringBuffer();
sb.append("Hello").append(" World");  // 不会产生新对象

3. StringBuilder:可变但不安全

  • 与 StringBuffer 功能完全相同,只是方法没有 synchronized 修饰。
  • 单线程环境下性能最佳(无锁竞争)。
  • 是 Java 1.5 引入的,用于替代 StringBuffer 在单线程场景。

示例

java

StringBuilder sb = new StringBuilder();
sb.append("Hello").append(" World");

三、性能对比与使用建议

1. 字符串拼接的优化

错误示例

java

String s = "";
for (int i = 0; i < 10000; i++) {
    s += i;   // 每次创建新的String
}

正确示例

java

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append(i);
}
String s = sb.toString();

2. 使用场景总结

  • 单线程、频繁修改:使用 StringBuilder(如循环拼接、JSON 构造)。
  • 多线程、频繁修改:使用 StringBuffer(如多线程日志输出)。
  • 字符串内容不变:使用 String(如常量、配置项、HashMap 的键)。
  • 少量拼接:编译器会自动优化,直接用 + 即可。

四、扩展知识

  • 初始容量StringBuilder 和 StringBuffer 默认初始容量为 16,如果预估最终字符串长度,可以在构造时指定容量,避免扩容带来的性能损耗。

    java

    StringBuilder sb = new StringBuilder(128); // 预分配容量
    
  • 线程安全成本StringBuffer 因为同步开销,在单线程下比 StringBuilder 慢约 10%~30%(取决于操作复杂度)。


五、总结

场景推荐类
字符串常量或少量拼接String
单线程大量拼接StringBuilder
多线程大量拼接StringBuffer

理解这三者的本质区别,可以帮助你写出更高效、更安全的 Java 代码。