StringBuilder 在高频运行时拼接、跨方法拼接、预知长度、需动态修改等场景下必须使用;应预设容量避免扩容,坚持链式 append,禁用字符串+号拼接和循环内 String+=,避免多线程共享或编译期常量场景滥用。

StringBuilder 不是万能的,但用对地方能带来几十倍性能提升;关键不在“用了没”,而在“怎么用”——尤其要避开默认容量、混用+号、线程误用这三类高频陷阱。
哪些场景必须用 StringBuilder
它不是为所有拼接而生,而是专治运行时高频、可积累的修改路径:
- 循环内拼接 ≥5 次,且每次追加内容平均超 10 字符(如组装日志行、生成 HTML 表格、拼 SQL WHERE 条件)
- 拼接逻辑分散在多个方法或回调中(如递归生成 JSON、模板引擎嵌套填充),编译器无法跨方法优化
- 已知最终长度范围(例如导出 5000 条记录,每条约 80 字符 + 分隔符),可预设容量避免扩容开销
- 需要动态插入前缀、删尾逗号、替换中间字段(如 sb.insert(0, "【"+type+"】") 或 sb.deleteCharAt(sb.length()-1))
初始化容量怎么设才不拖慢性能
默认容量 16 极易触发扩容,而每次扩容都要复制整个底层数组,代价不小。正确做法是预估而非依赖默认值:
- 能粗略估算总长就显式指定:比如拼 200 个平均 30 字符的字符串 + 199 个逗号,≈ 6199,写 new StringBuilder(6200)
- 不确定长度但数据量大(如万级日志缓冲),宁可略高估(设 8192),避免多次翻倍扩容(新容量 = 旧容量 × 2 + 2)
- 在 ThreadLocal<StringBuilder> 场景下,推荐固定容量(如 1024),复用前调用 setLength(0) 清空,比新建更轻量
链式 append 是高效写法的核心
StringBuilder 的价值在于复用内部 char 数组,一旦写法不当,所有优化立即失效:
立即学习“Java免费学习笔记(深入)”;
- 坚持链式调用:sb.append("id=").append(id).append(", name=").append(name) —— 支持多种类型参数,自动 toString(),无中间对象
- 禁用 sb.append("a" + "b"):编译器会先建临时 StringBuilder,再 toString,白费一次开销
- 绝对禁止循环内写 String s = ""; s += item;:每次迭代都新建 StringBuilder + String,时间复杂度接近 O(n²)
- 拼完务必调用 toString() 获取结果;非必要少用 insert/replace/reverse,它们涉及字符移动,开销远高于 append
别在错的地方硬套 StringBuilder
它不是银弹,盲目替换反而引入风险或冗余:
- 编译期确定的少量拼接(如 "Hello" + "World" 或 final String a = "a"; String s = a + "!";),JDK 会自动优化为常量,用 String 更简洁安全
- 只是把 List 拼成逗号分隔串?优先用 String.join(",", list) —— 内部已优化,还自动跳过 null 元素
- 多线程共享拼接逻辑?选 StringBuffer(同步安全)或改用 ThreadLocal 隔离,严禁 static 共享 StringBuilder 实例
- append(null) 在 JDK 8+ 会抛 NPE;需判空或统一用 Objects.toString(x, "") 再 append



















