String、StringBuffer、StringBuilder 的区别?¶
结论速查¶
| String | StringBuffer | StringBuilder | |
|---|---|---|---|
| 可变性 | 不可变 | 可变 | 可变 |
| 线程安全 | 安全(不可变) | 安全(方法 synchronized) | 不安全 |
| 性能 | 低(每次拼接新对象) | 中 | 高 |
| 使用场景 | 少量字符串操作 | 多线程共享 | 单线程拼接 |
一、String 不可变¶
底层是 private final char[] value(JDK9 后是 byte[] + 编码)。
二、StringBuffer¶
public final class StringBuffer extends AbstractStringBuilder {
public synchronized StringBuffer append(String str) { ... }
}
所有 public 方法都 synchronized,线程安全,但性能差。
三、StringBuilder¶
JDK 5 引入,与 StringBuffer 方法一样,只是去掉了 synchronized。
四、拼接性能对比¶
// 反例:循环拼接
String s = "";
for (int i = 0; i < 10000; i++) {
s += i; // 每次新建 StringBuilder,再 toString,慢
}
// 推荐
StringBuilder sb = new StringBuilder(10000);
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
JDK 编译器对 + 做了优化,会编译成 StringBuilder.append,但循环外每次 new 一个,仍慢。
五、JDK 9 的变化¶
String 底层从 char[] 改成 byte[] + coder:
- 纯 ASCII 用 1 字节存,省内存。
- 有非 ASCII 用 UTF-16,2 字节。
面试加分
- 单线程用 StringBuilder,多线程共享用 StringBuffer。
- 实际开发几乎不用 StringBuffer,多线程场景用局部变量 + StringBuilder 即可。