stringbuilder是可变、非线程安全的字符序列容器,底层为可扩容的byte[](jdk9+),所有操作就地修改、不创建新对象;单线程高频拼接时性能优于string(避免对象爆炸)和stringbuffer(无同步开销),但多线程共享使用会导致数据错乱。

面试中考察 StringBuilder,核心不是背定义,而是看你怎么理解它在真实场景中的定位和取舍。重点不在“它是什么”,而在“为什么用它、什么时候不能用、跟谁对比更合理”。
StringBuilder 的本质:可变的字符数组容器
它底层就是一个可扩容的 char[](JDK 9+ 是 byte[] + 编码标识),所有 append、insert、delete 操作都直接修改这个数组,不生成新对象。这点和 String 形成根本对立——String 每次拼接都 new 一个新对象,而 StringBuilder 就地修改。
- 默认初始容量是 16,不够时按 newCapacity = oldCapacity * 2 + 2 扩容
- 扩容会新建数组、复制旧内容,老数组等待 GC;频繁扩容会影响性能,但远好于 String 的对象爆炸
- 没有 final 修饰,也没有同步控制,所以它“裸奔”——高效但不安全
和 String 对比:别只说“可变 vs 不可变”,要说清代价
很多人答“StringBuilder 可变,所以快”,这太浅。面试官想听的是你是否理解背后的资源权衡:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- String 拼接循环(s += "x"):每次执行都创建新对象,10000 次循环 ≈ 10000 个临时 String,GC 压力大、内存碎片多
- StringBuilder.append("x"):复用同一对象,仅数组扩容几次,对象数≈1,GC 几乎无负担
- 但注意:如果只是拼接两三个字面量(如
"a" + "b" + "c"),编译器会优化成常量,String 反而更轻量——没必要强行换 StringBuilder
和 StringBuffer 对比:线程安全不是免费的午餐
两者 API 几乎一致,区别就一层薄纱:StringBuffer 方法全带 synchronized,StringBuilder 完全不加锁。
- 单线程下,StringBuilder 性能通常比 StringBuffer 高 10%–15%,因为省去了锁获取/释放开销
- 多线程共享同一个 StringBuilder 实例?结果不可预测——可能丢字符、顺序错乱、甚至抛 ArrayIndexOutOfBoundsException
- 真正需要线程安全时,优先考虑是否必须共享实例:多数情况可改为局部变量(每个线程自己 new 一个 StringBuilder),比用 StringBuffer 更高效
高频陷阱题怎么拆解
比如问:“new StringBuilder("abc").append("def") 创建了几个对象?”
- 1 个 StringBuilder 实例(堆中)
- 内部 char[] 初始容量 16,存 "abc" 和 "def" 共 6 字符,无需扩容 → 没有额外数组对象
- 注意:
"abc"和"def"是字符串字面量,存在常量池,不算 StringBuilder 创建的对象 - 答案:1 个对象(不是 2 个,也不是“无数个”)
再如:“能否用 StringBuilder 作为 HashMap 的 key?”
- 不能。key 必须不可变,否则 hashcode 变化会导致 get 失败——StringBuilder 内容可变,且没重写 hashCode/equals,不符合 key 约束
- 反例提醒:String 可以当 key,正因为它不可变 + 正确重写了 hashCode 和 equals
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










