标准答案
- String 拼接在循环中可能产生大量临时对象,编译器只会优化部分简单表达式。
- StringBuilder 在一个线程内构建可变字符串,最后通过 toString 生成结果。
- StringBuffer 的方法带同步语义,但共享它并不自动保证整个业务操作原子。
- 字符串作为 Map key 的不可变特征有利于稳定哈希。
题目解析
String 不可变,适合作为值和 Map key;循环拼接如果每次创建新对象会增加分配,编译器对简单表达式的优化不能替代对复杂循环的判断。StringBuilder 适合单线程构建结果。
StringBuffer 的同步只覆盖单个方法调用,不会让“读取、判断、追加、提交”这样的业务流程自动原子。共享可变字符串通常还需要更清晰的所有权和锁边界。
intern 会把字符串放进字符串池并影响生命周期和内存,只有在明确重复字符串场景、版本行为和容量风险后才考虑。性能优化应由 profile 证明。
常见误区
- 误区:所有字符串拼接都手动改成 Builder。改正:先区分编译器可优化的简单表达式和真正的循环/热路径,保持代码清晰。
- 误区:以为 StringBuffer 能保护复杂业务状态。改正:同步方法不等于业务操作原子,必要时使用更高层锁或不可变结果。
- 误区:把 intern 当作通用缓存。改正:评估字符串池、内存和生命周期风险,普通缓存使用明确的容量和淘汰策略。