在 Java 中,主要有三种方式来实现字符串连接:

- 使用 运算符(最常用、最直观)
- 使用
String.concat()方法 - 使用
StringBuilder或StringBuffer(性能最高,尤其在循环中)
下面我们逐一介绍这三种方法,并分析它们的优缺点和适用场景。
使用 运算符
这是最常见、最符合直觉的方法,尤其是在拼接少量字符串时。
示例代码
public class StringConcatExample {
public static void main(String[] args) {
String str1 = "Hello, ";
String str2 = "World!";
// 使用 + 运算符连接字符串
String result = str1 + str2;
System.out.println(result); // 输出: Hello, World!
// 也可以连接字符串和其他类型(如数字)
int number = 100;
String info = "The number is: " + number;
System.out.println(info); // 输出: The number is: 100
}
}
工作原理(非常重要!)
当你使用 连接字符串时,Java 编译器会在底层悄悄地为你创建一个 StringBuilder 对象,然后调用其 append() 方法,最后再调用 toString() 方法返回结果。
以下代码:

String a = "a"; String b = "b"; String c = "c"; String result = a + b + c;
在编译后,其效果类似于:
String a = "a"; String b = "b"; String c = "c"; // 编译器自动创建 StringBuilder StringBuilder sb = new StringBuilder(); sb.append(a); sb.append(b); sb.append(c); String result = sb.toString();
优缺点
-
优点:
- 语法简洁:代码可读性高,非常直观。
- 功能强大:可以自动将任何数据类型(如
int,double,Object等)转换为字符串再进行连接。
-
缺点:
- 性能问题(在循环中):如果在循环里使用 ,会频繁地创建和销毁
StringBuilder对象,导致性能急剧下降。 - 不可变性:
String对象是不可变的,每次使用 连接,都会在内存中创建一个新的String对象,旧的String对象会被垃圾回收器回收,这会带来额外的内存开销。
- 性能问题(在循环中):如果在循环里使用 ,会频繁地创建和销毁
适用场景
- 适用于少量、非循环的字符串拼接。
- 在日志打印、简单的字符串组合等场景下非常方便。
使用 String.concat() 方法
String 类本身提供了一个 concat() 方法用于连接另一个字符串。

示例代码
public class StringConcatMethodExample {
public static void main(String[] args) {
String str1 = "Hello, ";
String str2 = "World!";
// 使用 concat() 方法连接字符串
String result = str1.concat(str2);
System.out.println(result); // 输出: Hello, World!
}
}
工作原理
concat() 方法直接在调用它的字符串对象后面追加传入的字符串,并返回一个新的 String 对象,它内部实现也依赖于 System.arraycopy 等数组拷贝方法来高效地创建新字符串。
优缺点
-
优点:
- 语义明确:代码清晰地表达了“连接”这个意图,比 更具描述性。
- 性能通常比 (在非循环中)稍好,因为它避免了
StringBuilder的创建开销。
-
缺点:
- 语法稍显冗长:没有 运算符简洁。
- 功能较弱:
concat()的参数必须是String类型,如果需要连接数字等其他类型,必须先调用String.valueOf()或Integer.toString()等方法进行转换,否则会编译错误。 - 同样,在循环中使用性能会很差。
适用场景
- 当你想明确表达连接操作,并且确定所有要连接的元素都是
String类型时。 - 适用于少量字符串的拼接。
使用 StringBuilder 或 StringBuffer
这是性能最高的字符串连接方式,特别是在需要拼接大量字符串或循环中。StringBuilder 和 StringBuffer 的用法几乎完全相同,核心区别在于线程安全。
StringBuilder:非线程安全,但性能更高(因为没有同步开销)。绝大多数情况下,你应该优先使用StringBuilder。StringBuffer:线程安全,方法上有关键字synchronized,在多线程环境下修改字符串内容时使用,但日常开发中很少遇到。
示例代码
public class StringBuilderExample {
public static void main(String[] args) {
String str1 = "Hello, ";
String str2 = "World!";
// 创建一个 StringBuilder 对象
StringBuilder sb = new StringBuilder();
// 使用 append() 方法追加字符串
sb.append(str1);
sb.append(str2);
// 使用 toString() 方法获取最终的 String 结果
String result = sb.toString();
System.out.println(result); // 输出: Hello, World!
// 也可以链式调用
String result2 = new StringBuilder().append("a").append("b").append("c").toString();
System.out.println(result2); // 输出: abc
}
}
工作原理
StringBuilder 内部维护一个可变的字符数组,当你调用 append() 方法时,它会将内容添加到这个数组中(如果数组不够大,会进行扩容),而不会创建新的对象,只有在最后调用 toString() 时,才会生成一个新的、不可变的 String 对象。
优缺点
-
优点:
- 性能卓越:在循环中或拼接大量字符串时,性能远超 和
concat(),因为它只在内存中维护一个可变对象,避免了频繁创建新对象的开销。 - 功能强大:
append()方法可以接受各种数据类型,就像 运算符一样。
- 性能卓越:在循环中或拼接大量字符串时,性能远超 和
-
缺点:
- 代码稍显繁琐:需要手动创建对象、调用方法,最后还要
toString(),没有 运算符那么简洁。
- 代码稍显繁琐:需要手动创建对象、调用方法,最后还要
适用场景
- 必须用于循环中拼接字符串。
- 需要拼接非常多的字符串,对性能有要求的场景。
- 在构建复杂的 SQL 语句、JSON 数据或 XML 数据时非常常用。
性能对比示例
下面是一个在循环中使用 和 StringBuilder 的性能对比,可以非常直观地看出差异。
public class PerformanceComparison {
public static void main(String[] args) {
int iterations = 100000;
// --- 使用 + 运算符 ---
long startTimePlus = System.nanoTime();
String resultPlus = "";
for (int i = 0; i < iterations; i++) {
resultPlus += "a"; // 每次循环都创建一个新的 String 对象
}
long endTimePlus = System.nanoTime();
System.out.println("Using + operator took: " + (endTimePlus - startTimePlus) / 1_000_000.0 + " ms");
// --- 使用 StringBuilder ---
long startTimeSB = System.nanoTime();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iterations; i++) {
sb.append("a"); // 在同一个对象上进行操作
}
String resultSB = sb.toString();
long endTimeSB = System.nanoTime();
System.out.println("Using StringBuilder took: " + (endTimeSB - startTimeSB) / 1_000_000.0 + " ms");
}
}
可能的输出结果(具体时间因机器而异):
Using + operator took: 125.456 ms
Using StringBuilder took: 2.891 ms
从结果可以看出,在循环中,StringBuilder 的性能比 运算符快了数十倍甚至更多。
总结与最佳实践
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 运算符 | 语法简洁,直观,可连接任意类型 | 循环中性能极差,频繁创建对象 | 少量、非循环的字符串拼接,如日志、简单赋值 |
concat() |
语义明确,性能比 (非循环) 稍好 | 语法稍长,只能连接 String 类型 |
少量 String 对象的连接,强调连接意图 |
**StringBuilder |
