必须用StringBuilder的场景是循环内拼接、日志组装、XML/JSON构建、模板渲染等动态生成字符串且拼接次数≥3次的运行时操作;错误示范为循环中用String累加。

String 和 StringBuilder 的性能差异,核心不在“写法”,而在“对象生命周期”和“内存行为”。用错场景时,String 拼接可能慢上千倍;用对了,StringBuilder 甚至能扛住每秒数万次的字符串构建。
什么时候必须用 StringBuilder?
循环内拼接、日志组装、XML/JSON 构建、模板渲染等动态生成字符串的场景,只要拼接次数 ≥ 3 次,且发生在运行时(非编译期常量),就该换 StringBuilder。
- ❌ 错误示范:String s = ""; for (int i = 0; i —— 每次 += 实际触发 new StringBuilder().append(...).toString(),1000 次循环新建 1000 个 StringBuilder + 1000 个 String 对象
- ✅ 正确写法:StringBuilder sb = new StringBuilder(); for (int i = 0; i
- ? 小技巧:预估长度可减少扩容。例如拼接 1000 个数字(平均 4 字符),初始容量设为 4000:new StringBuilder(4000)
String 真的不能拼接?不是的,但要看时机
String 的 "+" 拼接在编译期会被优化,仅适用于字面量或 final 常量组合,此时不产生运行时开销。
- ✔ 编译期优化有效:String s = "Hello" + "World"; → 直接编译为 "HelloWorld",零对象创建
- ✔ 多常量拼接也安全:final String a = "a"; final String b = "b"; String s = a + b + "!"; → 同样内联为常量
- ❌ 运行时变量不行:String s = prefix + name + suffix;(prefix/name/suffix 非 final)→ 触发 StringBuilder 临时对象创建
StringBuilder 性能关键点:扩容与复用
StringBuilder 默认初始容量是 16,当字符数超过容量时,会扩容为 旧容量 × 2 + 2,并复制整个数组。频繁扩容会拖慢性能,尤其在大数据量拼接中。
立即学习“Java免费学习笔记(深入)”;
- 查当前容量:sb.capacity();查已用长度:sb.length()
- 避免反复创建:在方法内重复使用同一 StringBuilder 实例(注意线程隔离),比每次 new 更高效
- 清空重用:sb.setLength(0) 比 new StringBuilder() 开销小得多,适合循环内复用
别忘了 StringBuffer:它没被淘汰,只是用得少
StringBuffer 和 StringBuilder 底层完全一致,唯一区别是所有 public 方法都加了 synchronized。如果你的字符串构建逻辑跨多个线程共享(如全局日志缓冲区),且无法用 ThreadLocal 隔离,StringBuffer 仍是安全选择。
- 性能代价:同步块带来约 50%~100% 的吞吐下降(实测 JDK17 下 10 万次拼接:StringBuilder 12ms vs StringBuffer 28ms)
- 替代方案更推荐:ThreadLocal
,每个线程独享实例,无锁又安全 - 现代补充:JDK14+ 提供了实验性 ConcurrentStringBuilder(需显式启用),但生产环境仍建议优先用 ThreadLocal



















