文章目录
- 前言
- [String 的不可变性](#String 的不可变性)
- [StringBuffer 可变且线程安全](#StringBuffer 可变且线程安全)
- [StringBuilder 可变但线程不安全](#StringBuilder 可变但线程不安全)
- 三者进行比较
- 典型面试
前言
String 的不可变性
String一旦创建,其内部 char[ ] 数组(Java 9 后为 byte[ ])被 final 修饰,且没有提供任何修改内部状态的方法。任何看似修改的操作(如 concat( )、replace( )、+ 运算符)都会创建新的 String 对象。
java
String s = "hello";
s = s + " world"; // 实际生成了新的 String 对象,原 "hello" 变成垃圾
- 优点:线程安全、可以缓存 hashCode(适合作为 HashMap 的 key)、安全性(如类加载、网络连接等场景)。
- 缺点:频繁拼接会产生大量临时对象,消耗内存和 GC 时间。
StringBuffer 可变且线程安全
StringBuffer 继承自 AbstractStringBuilder,内部维护可变的字符数组
java
StringBuffer sb = new StringBuffer("hello");
sb.append(" world"); // 直接在原对象上操作,不产生新对象
StringBuilder 可变但线程不安全
与 StringBuffer API 完全相同,唯一区别是不加 synchronized。性能最高,是单线程字符串拼接的首选。
注意:如果多个线程同时访问,可能抛出异常或产生不可预料的结果。
三者进行比较
典型面试
1.String 为什么设计成不可变?
- 字符串常量池的需要:多个引用指向同一个字符串常量时,一个修改不会影响其他引用。
- 安全:类加载、数据库连接、文件路径等场景避免被篡改。
- 线程安全:无需额外同步。
- 哈希值可缓存:作为 HashMap 的 key 时效率高。
2.StringBuffer 与 StringBuilder 选择原则?
- 单线程:优先 StringBuilder,没有同步开销,性能更好。
- 多线程:用 StringBuffer,或使用 StringBuilder 并自行加锁(但更麻烦)。
java
java
java