侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

Java中String、StringBuilder和StringBuffer的区别与应用场景

2025-12-5 / 0 评论 / 4 阅读

题目

Java中String、StringBuilder和StringBuffer的区别与应用场景

信息

  • 类型:问答
  • 难度:⭐⭐

考点

字符串处理,不可变性,线程安全,性能优化

快速回答

核心区别:

  • String:不可变对象,线程安全但频繁修改效率低
  • StringBuilder:可变对象,非线程安全,单线程下性能最佳
  • StringBuffer:可变对象,线程安全(synchronized方法),多线程场景适用

选择原则:

  1. 字符串不修改时用 String
  2. 单线程频繁修改用 StringBuilder
  3. 多线程环境修改用 StringBuffer
## 解析

一、核心原理

1. String 的不可变性

String str = "Hello";
str += " World";  // 实际创建新对象"Hello World",原对象未修改
  • 每次修改都生成新对象,旧对象等待GC回收
  • 导致频繁内存分配和垃圾回收,影响性能

2. StringBuilder/StringBuffer 的可变性

StringBuilder sb = new StringBuilder();
sb.append("Hello");  // 修改内部char[]数组
sb.append(" World"); // 数组扩容后继续修改
  • 内部维护可变char[]数组,修改时不创建新对象
  • 初始容量16,自动扩容(新容量 = 旧容量*2 + 2)

二、线程安全对比

类名线程安全实现方式
String不可变特性天然安全
StringBuilder无同步控制
StringBuffer关键方法添加synchronized

三、性能测试示例

// 测试10万次拼接
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 100000; i++) {
    s += i;  // 每次循环创建新对象
}
System.out.println("String耗时: " + (System.currentTimeMillis()-start));

start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
    sb.append(i);  // 直接修改内部数组
}
System.out.println("StringBuilder耗时: " + (System.currentTimeMillis()-start));

典型结果:String耗时 > 5000ms,StringBuilder耗时 < 10ms

四、最佳实践

  1. 字符串常量:直接使用 String(如:String url = "https://example.com")
  2. 循环内拼接:必须用 StringBuilder(避免在循环内用 + 拼接)
  3. 预分配容量:已知最终长度时初始化容量提升性能
    // 已知最终长度约1000
    StringBuilder sb = new StringBuilder(1000);
  4. 多线程场景:使用 StringBuffer 或外部同步
    // 方案1:使用StringBuffer
    StringBuffer safeBuffer = new StringBuffer();
    
    // 方案2:外部同步StringBuilder
    StringBuilder sb = new StringBuilder();
    synchronized(lockObject) {
        sb.append(data);
    }

五、常见错误

  • 错误1:在循环中使用 + 拼接字符串
    // 反例:产生大量临时对象
    String result = "";
    for (String str : list) {
        result += str;
    }
  • 错误2:多线程环境误用非线程安全的StringBuilder
  • 错误3:不需要线程安全时使用StringBuffer(有同步开销)

六、扩展知识

  • 字符串驻留(Interning):String.intern() 方法将字符串加入常量池
  • Java 9 优化:String 内部存储改为 byte[] + 编码标记,节省内存
  • 模式匹配:Java 17 的 switch 模式匹配可优化字符串分支处理