第34题:String、StringBuffer和StringBuilder的区别是什么
📚 回答:
- 核心对比 :
String、StringBuffer和StringBuilder是 Java 中处理字符串的三种主要方式,它们在可变性 、线程安全性 和性能上有显著差异。以下是详细对比:
1. String
-
定义:
String是一个不可变的字符串对象,一旦创建,其内容无法更改。- 每次对字符串进行修改(如拼接)时,都会生成一个新的
String对象。
-
底层实现:
- 底层基于字符数组实现,但由于不可变性,每次修改都会创建新的数组。
-
优点:
- 线程安全:因为内容不可变,多线程环境下无需额外同步。
- 使用简单:适用于大多数场景,尤其是不需要频繁修改字符串的情况。
-
缺点:
- 性能较差:频繁修改会导致大量临时对象产生,增加内存开销。
💡 代码示例 :
以下代码展示了
String的不可变性:
java
String str = "Hello";
str += " World"; // 创建了一个新的String对象
System.out.println(str); // 输出 "Hello World"
2. StringBuffer
-
定义:
StringBuffer是一个可变的字符串对象,支持直接修改内容。- 底层基于字符数组实现,默认初始容量为 16 字节。
-
线程安全性:
- 方法使用
synchronized关键字修饰,保证线程安全,适合多线程环境。
- 方法使用
-
扩容机制:
- 当现有容量不足时,会自动扩容为原容量的 2 倍 + 2(即
(oldCapacity * 2) + 2)。
- 当现有容量不足时,会自动扩容为原容量的 2 倍 + 2(即
-
优点:
- 线程安全:适合多线程场景下的字符串操作。
-
缺点:
- 性能较低:由于加锁机制,效率低于
StringBuilder。
💡 代码示例 :
以下代码展示了
StringBuffer的用法: - 性能较低:由于加锁机制,效率低于
java
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World"); // 直接修改原有对象
System.out.println(sb); // 输出 "Hello World"
3. StringBuilder
-
定义:
StringBuilder是一个可变 的字符串对象,与StringBuffer类似,但不保证线程安全。
-
性能优势:
- 不使用
synchronized关键字,因此在单线程环境下性能优于StringBuffer。
- 不使用
-
适用场景:
- 单线程环境下需要频繁修改字符串的场景。
💡 代码示例 :
以下代码展示了
StringBuilder的用法:
java
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 直接修改原有对象
System.out.println(sb); // 输出 "Hello World"
4. 对比总结
| 特性 | String |
StringBuffer |
StringBuilder |
|---|---|---|---|
| 可变性 | 不可变 | 可变 | 可变 |
| 线程安全性 | 线程安全 | 线程安全 | 非线程安全 |
| 性能 | 较低(频繁修改时) | 较低(加锁开销) | 较高(无锁) |
| 适用场景 | 字符串内容固定或较少修改 | 多线程环境下的字符串操作 | 单线程环境下的字符串操作 |
💡 面试官视角:
- 面试官可能会问"为什么
String是不可变的?"
答:不可变性保证了线程安全,避免多线程环境下数据竞争问题。 - 面试官可能会追问"
StringBuffer和StringBuilder的扩容机制有什么区别?"
答:两者扩容机制相同,都是(oldCapacity * 2) + 2,但StringBuffer因为加锁,性能略低。
📌 专栏 :大白话说Java面试题 --- 01-Java基础篇