Java 中 String、StringBuffer 和 StringBuilder 的区别是什么?

在 Java 中,StringStringBufferStringBuilder都是用于处理字符串的类,但它们在可变性、线程安全性和性能方面有重要区别。以下是详细的对比:

1. String(字符串常量)

  • 不可变性String对象创建后不可改变,任何修改操作都会生成新的对象
  • 线程安全:由于不可变,天生线程安全
  • 存储位置:字符串常量池(字面量)或堆内存(new创建)
  • 性能:频繁修改时效率低(产生大量垃圾对象)
String str = "Hello";
str = str + " World";  // 创建了新对象,原对象未变

2. StringBuffer(字符串变量)

  • 可变性:内容可以修改,不会创建新对象
  • 线程安全:方法使用 synchronized关键字修饰,线程安全
  • 性能:比 String在频繁修改时效率高得多
  • 同步开销:由于同步,单线程环境下性能略低于 StringBuilder
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");  // 在原对象上修改

3. StringBuilder(字符串变量)

  • 可变性:同 StringBuffer,内容可修改
  • 线程安全非线程安全,没有同步
  • 性能:在单线程环境下性能最高
  • Java版本:JDK 1.5+ 引入
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");  // 在原对象上修改

详细对比表

特性StringStringBufferStringBuilder
可变性不可变可变可变
线程安全是(天生)是(同步)
性能最低(频繁修改时)中等(有同步开销)最高(无同步)
使用场景字符串不常修改多线程环境字符串频繁修改单线程环境字符串频繁修改
内存效率低(频繁修改时)
初始化String s = "abc";new String("abc")new StringBuffer("abc")new StringBuilder("abc")

性能测试示例

public class PerformanceTest {
    public static void main(String[] args) {
        int N = 100000;
        
        // String 测试
        long start = System.currentTimeMillis();
        String str = "";
        for (int i = 0; i < N; i++) {
            str += i;  // 每次拼接都创建新对象
        }
        System.out.println("String 耗时: " + (System.currentTimeMillis() - start) + "ms");
        
        // StringBuffer 测试
        start = System.currentTimeMillis();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < N; i++) {
            sb.append(i);
        }
        System.out.println("StringBuffer 耗时: " + (System.currentTimeMillis() - start) + "ms");
        
        // StringBuilder 测试
        start = System.currentTimeMillis();
        StringBuilder sbd = new StringBuilder();
        for (int i = 0; i < N; i++) {
            sbd.append(i);
        }
        System.out.println("StringBuilder 耗时: " + (System.currentTimeMillis() - start) + "ms");
    }
}

使用建议

使用 String​ 的场景:

  • 字符串不经常修改
  • 需要字符串常量
  • 线程安全要求高
  • 作为 HashMap 的键(利用不可变性)

使用 StringBuffer​ 的场景:

  • 多线程环境下频繁修改字符串
  • 需要线程安全保证

使用 StringBuilder​ 的场景:

  • 单线程环境下频繁修改字符串
  • 性能要求高的场景
  • 方法内部的局部变量

注意事项

  1. 编译器优化:现代 Java 编译器会对 String+操作进行优化,在简单情况下自动使用 StringBuilder
  2. 循环中的字符串拼接:在循环中避免使用 String+操作
  3. 线程安全选择:根据实际需求选择线程安全版本

总结

  • 不可变 vs 可变String不可变,StringBuffer/StringBuilder可变
  • 线程安全StringStringBuffer安全,StringBuilder不安全
  • 性能StringBuilder> StringBuffer> String(频繁修改时)

根据具体场景选择合适的类,能显著提升程序性能。


作 者:南烛
链 接:https://www.itnotes.top/archives/999
来 源:IT笔记
文章版权归作者所有,转载请注明出处!


上一篇
下一篇