在 Java 中,String
、StringBuilder
和 StringBuffer
是用于处理字符串的三种主要类。它们各有特点,适用于不同的场景。本文将详细解析它们的区别,并通过示例代码加深理解。
1. String
1.1 特点
- 不可变性:
String
是不可变的(immutable),即一旦创建,其内容就不能被修改。 - 线程安全:由于不可变性,
String
是线程安全的。 - 性能:频繁修改字符串时,会产生大量临时对象,影响性能。
1.2 适用场景
- 字符串内容不需要修改的场景。
- 多线程环境下需要线程安全的场景。
1.3 示例
String str = "Hello";
str = str + " World"; // 创建了一个新的 String 对象
System.out.println(str); // 输出: Hello World
2. StringBuilder
2.1 特点
- 可变性:
StringBuilder
是可变的(mutable),可以直接修改其内容。 - 非线程安全:
StringBuilder
不是线程安全的。 - 性能:由于避免了创建临时对象,
StringBuilder
在频繁修改字符串时性能更高。
2.2 适用场景
- 单线程环境下需要频繁修改字符串的场景。
2.3 示例
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 直接修改 StringBuilder 对象
System.out.println(sb.toString()); // 输出: Hello World
3. StringBuffer
3.1 特点
- 可变性:
StringBuffer
是可变的(mutable),可以直接修改其内容。 - 线程安全:
StringBuffer
是线程安全的,所有方法都使用synchronized
关键字进行同步。 - 性能:由于同步机制,
StringBuffer
的性能略低于StringBuilder
。
3.2 适用场景
- 多线程环境下需要频繁修改字符串的场景。
3.3 示例
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World"); // 直接修改 StringBuffer 对象
System.out.println(sb.toString()); // 输出: Hello World
4. 三者的区别总结
特性 | String | StringBuilder | StringBuffer |
---|---|---|---|
可变性 | 不可变 | 可变 | 可变 |
线程安全 | 线程安全 | 非线程安全 | 线程安全 |
性能 | 频繁修改时性能较低 | 频繁修改时性能高 | 频繁修改时性能略低于 StringBuilder |
适用场景 | 字符串内容不需要修改的场景 | 单线程环境下频繁修改字符串的场景 | 多线程环境下频繁修改字符串的场景 |
5. 性能对比
以下是一个简单的性能对比示例,展示 String
、StringBuilder
和 StringBuffer
在频繁修改字符串时的性能差异。
public class PerformanceTest {
public static void main(String[] args) {
int n = 100000;
// 使用 String
long startTime = System.currentTimeMillis();
String str = "";
for (int i = 0; i < n; i++) {
str += i;
}
long endTime = System.currentTimeMillis();
System.out.println("String time: " + (endTime - startTime) + " ms");
// 使用 StringBuilder
startTime = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append(i);
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder time: " + (endTime - startTime) + " ms");
// 使用 StringBuffer
startTime = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < n; i++) {
sbf.append(i);
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer time: " + (endTime - startTime) + " ms");
}
}
输出示例:
String time: 5000 ms
StringBuilder time: 10 ms
StringBuffer time: 15 ms
6. 总结
String
:不可变,线程安全,适用于字符串内容不需要修改的场景。StringBuilder
:可变,非线程安全,性能高,适用于单线程环境下频繁修改字符串的场景。StringBuffer
:可变,线程安全,性能略低于StringBuilder
,适用于多线程环境下频繁修改字符串的场景。