Java中 String、StringBuilder 和 StringBuffer 的区别?
在Java中,String
、StringBuilder
和 StringBuffer
都用于处理字符串,但它们在可变性、线程安全性和性能上有显著区别。以下是它们的对比:
1. String
- 不可变性(Immutable)
String
对象一旦创建,内容不可修改。任何修改操作(如拼接、替换)都会生成新的String
对象。java
String s = "hello";
s += " world"; // 创建新对象,原对象"hello"不变
- 线程安全
由于不可变,String
是线程安全的。 - 性能问题
频繁修改字符串(如循环拼接)会产生大量临时对象,影响性能。
2. StringBuilder
- 可变性(Mutable)
StringBuilder
的内容可以修改,直接在原对象上操作,不会创建新对象。java
StringBuilder sb = new StringBuilder("hello");
sb.append(" world"); // 直接修改原对象
- 非线程安全
方法未加同步锁,多线程环境下不安全。 - 高性能
适合单线程下的频繁字符串操作(如循环拼接)。
3. StringBuffer
- 可变性(Mutable)
与StringBuilder
类似,内容可修改。java
StringBuffer sb = new StringBuffer("hello");
sb.append(" world"); // 直接修改原对象
- 线程安全
方法通过synchronized
加锁,保证多线程安全,但性能略低。 - 适用场景
需要线程安全的字符串操作(如全局共享的字符串缓冲区)。
对比总结
特性 | String | StringBuilder | StringBuffer |
---|---|---|---|
可变性 | 不可变 | 可变 | 可变 |
线程安全 | 是 | 否 | 是 |
性能 | 低(频繁修改) | 高(单线程) | 较低(线程安全开销) |
适用场景 | 字符串常量 | 单线程频繁修改 | 多线程字符串操作 |
如何选择?
- 优先用
String
:字符串内容不变化或初始化后不再修改时(如配置信息)。 - 单线程频繁修改:用
StringBuilder
(如循环拼接字符串)。 - 多线程环境:用
StringBuffer
(或通过局部变量避免共享)。
示例代码
java
// String 拼接(产生多个对象) |
String s = "a"; |
for (int i = 0; i < 10; i++) { |
s += "b"; // 每次循环创建新对象 |
} |
// StringBuilder(高效单线程拼接) |
StringBuilder sb = new StringBuilder("a"); |
for (int i = 0; i < 10; i++) { |
sb.append("b"); // 直接修改原对象 |
} |
// StringBuffer(线程安全拼接) |
StringBuffer sbf = new StringBuffer("a"); |
synchronized(sbf) { // 手动同步(非必须,append本身是线程安全的) |
sbf.append("b"); |
} |
理解这些区别有助于根据场景选择最优的字符串处理方式。