Java中字符串拼接"+"底层编译期优化字面量合并,变量拼接转StringBuilder.append();循环内避免+=,应显式用StringBuilder;String.join()适合固定分隔符连接集合,String.concat()因功能单一少用。

用 + 拼接字符串时,底层到底发生了什么
Java 中写 "a" + "b" 看似简单,但编译器会按场景做不同优化。字面量拼接(如 "hello" + "world")在编译期就合并为一个常量,不产生运行时开销;但含变量时(如 str1 + str2),JDK 8+ 默认编译成 StringBuilder.append() 调用——前提是方法内联没被禁用、且没有嵌套复杂表达式。
常见误区是认为 + 总是低效。其实单条语句中连续拼接(如 "a" + x + y + "z")基本等价于手写 StringBuilder;但循环内写 result += s 就真会反复创建新对象,因为每次 += 都隐式新建 StringBuilder 再 toString()。
- 循环拼接必须显式用
StringBuilder,别依赖+ - 方法参数多、逻辑分支多时,
+可能无法被 JIT 充分优化,建议直接上StringBuilder - Android 开发注意:旧版 Dalvik 对
+优化弱,StringBuilder更稳
String.join() 适合什么场景
String.join() 是 JDK 8 引入的便捷方法,专用于「用同一分隔符连接多个字符串」,比如把 List 合并成 CSV。它内部用 StringBuilder 实现,性能可靠,代码也干净。
但它不处理 null 元素:传入 null 会直接抛 NullPointerException;也不支持格式化(比如对每个元素加引号或转义)。如果数据源可能含 null,得先过滤或映射:
立即学习“Java免费学习笔记(深入)”;
本文档主要讲述的是Android数据格式解析对象JSON用法;JSON可以将Java对象转成json格式的字符串,可以将json字符串转换成Java。比XML更轻量级,Json使用起来比较轻便和简单。JSON数据格式,在Android中被广泛运用于客户端和服务器通信,在网络数据传输与解析时非常方便。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
String joined = String.join(",", list.stream()
.map(Objects::toString)
.collect(Collectors.toList()));- 只适用于「固定分隔符 + 简单字符串集合」,别试图用它做模板填充
- 分隔符为空字符串
""时合法,但要注意结果长度可能爆炸 - 比手写循环 +
StringBuilder略慢(有 Stream 开销),但可读性高得多
为什么 String.concat() 很少被用到
String.concat() 是 Java 早期就有的方法,功能单一:只接受一个 String 参数,返回新字符串。它比 + 多一次非空检查,但没任何额外能力。JDK 源码里它的实现就是 new char[] + System.arraycopy,和 StringBuilder.toString() 底层逻辑类似,但无法链式调用、不能复用缓冲区。
- 拼两个字符串?
+更自然;拼多个?String.join()或StringBuilder更合适 - 它不重载,不能像
StringBuilder.append()那样接受int、boolean等自动装箱类型 - 唯一优势可能是语义明确——但实际开发中几乎没人靠方法名判断意图
拼接大量字符串时,StringBuilder 的容量设置很关键
默认构造 StringBuilder() 初始容量是 16,一旦追加内容超过,就会扩容(通常是翻倍 +1),触发数组复制。如果预估最终长度(比如拼 1000 个平均 50 字符的字符串),直接指定容量能避免多次扩容:
StringBuilder sb = new StringBuilder(1000 * 50); // 预分配
但别过度优化:容量设太大浪费堆内存;设太小又频繁复制。更稳妥的做法是用 StringBuilder(int capacity) 构造,或对已知大小集合用 String.join()。
- 从
String构造时,new StringBuilder(str)容量 =str.length() + 16,不是str.length() -
StringBuilder.setLength(0)可清空内容但保留容量,适合复用实例 - 多线程环境下必须用
StringBuffer,但同步开销明显,优先考虑无锁设计
真正容易被忽略的是:拼接逻辑分散在多层方法调用中时,很难预估总长度,这时候宁可让 StringBuilder 自动扩容,也别为了省几次复制去硬算容量——可维护性比那点微秒级差异重要得多。









