一、String:不可变性的设计哲学
1. 不可变性的本质
String的不可变性不是简单的限制,而是深度工程决策:
public final class String {
private final char value[]; // Java 8及之前
private final byte value[]; // Java 9+的紧凑字符串优化
private final int hash; // 缓存哈希值
}
-
final类:禁止继承破坏不可变性
-
final字符数组:创建后引用不可变
-
无修改方法:所有"修改"操作都返回新对象
2. 内存机制详解
String s1 = "Fly"; // 常量池创建
String s2 = new String("Fly"); // 堆中创建新对象
String s3 = s1.concat("Code"); // 新建String对象
System.out.println(s1 == s2); // false
System.out.println(s1 == s3); // false
-
常量池优化:相同字面量共享内存(通过
intern()
可手动入池) -
拼接代价:
s1 + s2
编译为new StringBuilder().append(s1).append(s2).toString()
二、StringBuffer:线程安全的代价
1. 同步机制实现原理
public final class StringBuffer extends AbstractStringBuilder {
@Override
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
// 所有public方法均添加synchronized
}
-
方法级锁:每个public方法使用
synchronized
修饰 -
对象锁:锁定当前StringBuffer实例
2. 扩容算法解析
初始容量16字符,扩容策略:
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2; // 2倍+2策略
if (newCapacity < minimumCapacity)
newCapacity = minimumCapacity;
if (newCapacity < 0) // 溢出处理
newCapacity = Integer.MAX_VALUE;
value = Arrays.copyOf(value, newCapacity);
}
-
指数扩容:减少频繁扩容开销
-
空间换时间:预分配额外空间避免频繁复制
3. 线程安全场景
StringBuffer buffer = new StringBuffer();
// 多线程并发追加
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
executor.submit(() -> buffer.append(Thread.currentThread().getName()));
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
// 结果长度正确(无数据丢失)
System.out.println(buffer.length()); // 输出约7000字符
三、StringBuilder:极致的单线程性能
1. 无锁设计实现
public final class StringBuilder extends AbstractStringBuilder {
@Override
public StringBuilder append(String str) {
super.append(str); // 无同步操作!
return this;
}
// 所有方法无synchronized
}
-
继承相同基类:与StringBuffer共享AbstractStringBuilder
-
方法无同步:消除锁开销
四、三维对比:核心差异全景图
特性维度 | String | StringBuffer | StringBuilder |
---|---|---|---|
可变性 | 不可变 | 可变 | 可变 |
线程安全 | 是(天然) | 是(同步锁) | 否 |
性能 | 最低(对象创建开销) | 中(锁开销) | 最高(无锁) |
内存效率 | 常量池优化 | 堆内存分配 | 堆内存分配 |
扩容机制 | 不适用 | 2倍+2策略 | 同StringBuffer |
JIT优化 | 常量折叠 | 锁消除(有限) | 无限制优化 |
使用场景 | 静态字符串、配置项 | 多线程日志拼接 | 单线程字符串操作 |