StringBuilder 专为高效字符串拼接设计,非替代 String;其可变性与预估容量可避免 O(N²) 开销和频繁扩容,多线程应选 StringBuffer,append(null) 会转为字符串“null”,toString() 后仍可复用。

Java 中 StringBuilder 的面试题通常不考死记硬背,而是考察你是否真正理解它的设计意图、适用场景和常见陷阱。核心就一点:它不是为“替代 String”而存在,而是为“高效拼接”而生。
为什么不用 String 拼接?
String 是不可变的,每次 + 或 concat() 都会新建对象。循环中拼接 N 次,可能产生 N 个中间字符串对象,时间和空间开销都是 O(N²)。
StringBuilder 是可变的,内部用 char 数组扩容(默认容量 16),append 操作平均时间复杂度接近 O(1)。
建议:
• 循环内拼接、多段字符串组合、XML/JSON 构建等场景,优先选 StringBuilder
• 简单两三个字面量拼接(如 "a" + "b" + "c"),编译器会自动优化成 StringBuilder,不用手动改
• 多线程环境别直接用 StringBuilder,改用 StringBuffer 或同步处理
扩容机制怎么影响性能?
StringBuilder 底层是 char[],初始容量 16。当 append 超出当前容量时,会触发扩容:新容量 = 旧容量 × 2 + 2(JDK 8+)。频繁扩容会带来数组复制开销。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
建议:
• 如果能预估最终长度(比如拼接 1000 条日志,每条平均 50 字符),构造时指定容量:new StringBuilder(50000)
• 不确定长度但知道上限,也建议设合理初始值,避免多次扩容
• 扩容本身不可怕,可怕的是在高频循环里反复触发(比如没预估、又没重用 StringBuilder 实例)
常见误用与对比辨析
面试官常通过对比题考察理解深度:
• StringBuilder vs StringBuffer:前者非线程安全、快;后者方法加了 synchronized,适合多线程共享场景,但性能低约 10%–15%
• StringBuilder vs String.join():后者适合拼接已有集合(如 List
• append(null) 的行为:不会报空指针,而是追加字符串 "null" —— 这是易错点,实际开发中要注意判空或用 Objects.toString()
• toString() 后的 StringBuilder 能否复用? 可以,toString() 返回新 String,不影响原实例状态,后续还能继续 append
一个典型实战小题(可直接用于面试手写)
题目:实现一个方法,把 List
参考写法:
public static String join(List<String> list, String delimiter) {
if (list == null || list.isEmpty()) return "";
if (list.size() == 1) return list.get(0);
<pre class="brush:php;toolbar:false;">// 预估容量:所有字符串长度 + 分隔符总长(size-1 个)
int len = list.stream().mapToInt(String::length).sum();
len += delimiter.length() * (list.size() - 1);
StringBuilder sb = new StringBuilder(len);
sb.append(list.get(0));
for (int i = 1; i < list.size(); i++) {
sb.append(delimiter).append(list.get(i));
}
return sb.toString();}
这个实现体现了容量预估、避免重复扩容、边界处理等关键点,比无脑 new StringBuilder() 更专业。

















