String vs StringBuilder vs StringBuffer深度解析

Java 面试核心:String vs StringBuilder vs StringBuffer 深度解析

一、三者核心区别一览

特性 String StringBuilder StringBuffer
可变性 不可变 (Immutable) 可变 (Mutable) 可变 (Mutable)
线程安全 安全(但无关,因为不可变) 不安全 安全(synchronized)
性能 低(每次操作创建新对象) (单线程最快) 中(同步带来开销)
使用场景 字符串常量、少量操作 单线程大量字符串拼接 多线程大量字符串拼接
JDK版本 1.0 1.5 1.0

二、String 的不可变性(Immutable)

为什么不可变?

java 复制代码
// 典型面试代码
String s = "hello";
s = s + " world";  // 创建了新对象,s指向新引用,"hello"被GC

不可变的好处:

  1. 字符串常量池复用 --- 节省内存
  2. HashCode 缓存 --- 适合作为 HashMap 的 Key
  3. 线程安全 --- 天然并发安全
  4. 安全 --- 防止参数被篡改(如网络传输、文件路径)

经典面试题

Q:以下代码创建了几个对象?

java 复制代码
String s1 = new String("abc");

A:2个 --- 堆中的 new String() 对象 + 常量池中的 "abc"
Q:String.intern() 的作用?
A: 将字符串放入常量池,返回常量池引用。用于手动控制字符串复用。


三、StringBuilder vs StringBuffer 源码级对比

1. 线程安全差异(核心考点)

java 复制代码
// StringBuffer:方法加 synchronized
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

// StringBuilder:无同步,裸奔
public StringBuilder append(String str) {
    super.append(str);
    return this;
}

2. 扩容机制(两者相同)

java 复制代码
// 默认初始容量 16,扩容:新容量 = 旧容量 × 2 + 2
void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    // ...
}

面试建议: 预估长度时用 new StringBuilder(100) 避免频繁扩容。


四、性能对比实测

操作 耗时 说明
String + 循环10000次 很慢 创建大量临时对象
StringBuilder 单线程 最快 无锁,直接操作字符数组
StringBuffer 单线程 较慢 同步锁开销
StringBuffer 多线程 安全 正确性优先

结论: 单线程无脑用 StringBuilder,多线程才考虑 StringBuffer


五、高频面试题精编

Q1:为什么 String 设计成不可变的?

答: 安全(防篡改)、高效(常量池复用)、线程安全、HashCode 缓存。

Q2:+ 操作符底层用什么?

答: JDK8+ 编译器自动转为 StringBuilder.append(),但循环中会每次新建 Builder,应手动用 Builder。

Q3:StringBuilder 为什么快?

答: 1)可变字符数组,原地修改;2)无同步锁开销;3)扩容时批量复制。

Q4:什么场景必须用 StringBuffer?

答: 多线程并发修改同一字符串对象时(实际很少见,通常用并发容器或局部变量)。


六、最佳实践速记

场景 推荐选择
字符串常量、配置项 String
单线程字符串拼接(循环、流处理) StringBuilder
多线程共享可变字符串(罕见) StringBuffer
高并发日志、序列化 StringBuilder(局部变量)

七、总结

String 是不可变的常量,StringBuilder 是单线程的快刀,StringBuffer 是多线程的保险柜。现代 Java 开发,90% 场景用 StringBuilder,剩下 9% 用 String,1% 才用 StringBuffer。


相关推荐
用户35218024547514 小时前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程
东坡白菜17 小时前
破局全栈:一个前端开发的Java入门实战记录(1)
java·全栈
唐青枫17 小时前
Java Tomcat 实战指南:从 Servlet 容器到 Spring Boot 部署
java
wsaaaqqq18 小时前
roudan:自由选择实体、灵活操作数据、快速写入数据库的 Java 框架
java
plainGeekDev21 小时前
null 判断 → Kotlin 可空类型
android·java·kotlin
糖拌西瓜皮21 小时前
Java开发者视角:深入理解Node.js异步编程模型
java·后端·node.js
plainGeekDev21 小时前
getter/setter → Kotlin 属性
android·java·kotlin
一线大码1 天前
Smart-Doc 的简单使用
java·后端·restful
MacroZheng1 天前
Claude Code官方桌面端正式发布,夯爆了!
java·人工智能·后端