Java基础 字符串类 String StringBuffer 和StringBuilder

字符串

  • 核心对比表
  • String:不可变字符串
  • StringBuffer:线程安全的可变字符串
    • 扩容机制:
  • StringBuilder:线程不安全的高效可变字符串
  • 使用场景决策树

1.String不可变字符串,任何修改都会创建新的字符串对象。
2.StringBuffer可变字符串, 线程安全(方法使用synchronized修饰),适合多线程环境
3.StringBuilder可变字符串, 非线程安全(没有同步),性能优于StringBuffer,适合单线程环境

核心对比表

特性 String StringBuffer StringBuilder
可变性 ❌ 不可变 ✅ 可变 ✅ 可变
线程安全 ✅(天生线程安全) ✅(synchronized 方法) ❌ 非线程安全
性能 ⚠️ 修改时效率低(创建新对象) ⚠️ 中等(同步开销) ✅ 高(无同步开销)
内存效率 ❌ 频繁修改时内存消耗大 ✅ 高效 ✅ 高效
适用场景 常量字符串、少量操作 多线程环境下的字符串操作 单线程环境下的字符串操作
JDK 版本 1.0+ 1.0+ 1.5+

String:不可变字符串

public final class String implements Serializable, Comparable<String>, CharSequence {
    private final char value[]; // 底层存储
    private int hash; // 缓存哈希值
}

核心特性:不可变性原理,任何修改都会创建新的字符串对象

不可变性原理
1.char[] 数组被声明为 final
2.类本身是 final(不可继承 不可修好 一经定义初始化存放常量池中)
3.无修改数组内容的公共方法

使用示例:

String s1 = "Hello";          // 字符串常量池
String s2 = new String("Hello"); // 堆内存新对象
String s3 = s1.concat(" World"); // 创建新对象

System.out.println(s1 == s2);   // false(不同对象)
System.out.println(s1.equals(s2)); // true(内容相同)

适用场景:

  • 字符串常量定义
  • 不需要修改的配置信息
  • HashMap 键值(利用不可变性)
  • 少量字符串操作

StringBuffer:线程安全的可变字符串

核心实现:

public final class StringBuffer extends AbstractStringBuilder {
    // 所有方法都添加了 synchronized 关键字
    @Override
    public synchronized StringBuffer append(String str) {
        super.append(str);
        return this;
    }
}

关键操作:

StringBuffer sb = new StringBuffer(); // 初始容量16
sb.append("Hello");      // 追加
sb.insert(5, " World");  // 插入 → "Hello World"
sb.replace(6, 11, "Java"); // 替换 → "Hello Java"
sb.reverse();            // 反转 → "avaJ olleH"
sb.delete(0, 5);         // 删除 → "Java"

扩容机制:

append操作--> 容量是否足够
容量足够:直接写入
容量不足够-->计算新容量 newCapacity = (oldCapacity * 2) + 2
-->创建新数组-->复制原数据放入新数组

StringBuilder:线程不安全的高效可变字符串

StringBuilder 与 StringBuffer 的对比

// StringBuilder 源码(无同步)
public final class StringBuilder extends AbstractStringBuilder {
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
}

// StringBuffer 源码(同步处理)
public final class StringBuffer extends AbstractStringBuilder {
    public synchronized StringBuffer append(String str) {
        super.append(str);
        return this;
    }
}

性能测试:

// 字符串拼接性能对比
int count = 100000;

// 1. String 拼接
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < count; i++) {
    s += i; // 每次循环创建新对象
}
System.out.println("String time: " + (System.currentTimeMillis()-start));

// 2. StringBuffer 拼接
start = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < count; i++) {
    sb.append(i);
}
System.out.println("StringBuffer time: " + (System.currentTimeMillis()-start));

// 3. StringBuilder 拼接
start = System.currentTimeMillis();
StringBuilder sbr = new StringBuilder();
for (int i = 0; i < count; i++) {
    sbr.append(i);
}
System.out.println("StringBuilder time: " + (System.currentTimeMillis()-start));

典型结果

String time: 4500 ms
StringBuffer time: 15 ms
StringBuilder time: 8 ms

使用场景决策树

需要操作字符串
是否需要修改内容
使用 String
是否多线程环境
使用 StringBuffer
使用 StringBuilder
少量操作/常量场景
WEB应用/并发处理
单线程循环/局部变量

终极建议

  • 80% 场景:优先使用 StringBuilder
  • 15% 场景:多线程共享时用 StringBuffer
  • 5% 场景:固定字符串用 String
  • 关键路径:预分配容量 + 避免不必要的转换

你可能感兴趣的:(java,基础,java,开发语言)