Java中String、StringBuffer和StringBuilder底层实现深入剖析

 更新时间:2026年01月08日 10:22:03   作者:Ricky_Ribbon  
在Java编程语言中String、StringBuffer和StringBuilder都是用来处理字符串的类,但它们之间存在显著的性能和功能差异,这篇文章主要介绍了Java中String、StringBuffer和StringBuilder底层实现的相关资料,需要的朋友可以参考下

前言

这三个类都是 java.lang 包下的字符串处理类,但它们在设计理念、内部实现和适用场景上存在显著差异。

1. 全面对比表

比较维度StringStringBufferStringBuilder
可变性不可变(Immutable)
内容一旦创建无法修改
可变(Mutable)
支持原地修改
可变(Mutable)
支持原地修改
线程安全天然线程安全(不可变对象)线程安全
关键方法(如 append、insert)加了 synchronized
非线程安全
无任何同步机制
性能修改操作最慢(频繁创建新对象)中等(有锁开销,但比 String 好)最高(无锁,单线程下最优)
内部存储底层是 final char[] value(JDK 7+)
JDK 8 前是 char[],不可扩容
底层是 char[] value,可动态扩容底层是 char[] value,可动态扩容(实现几乎相同)
容量扩容机制无(固定长度)默认容量 16,扩容时新容量 = (旧容量 * 2) + 2同 StringBuffer:默认 16,扩容时新容量 = (旧容量 * 2) + 2
内存占用每次修改产生新对象 + 新 char[],GC 压力大共享同一 char[],内存高效同 StringBuffer,内存高效
字符串常量池支持常量池缓存(字面量可复用)不支持常量池不支持常量池
引入版本JDK 1.0JDK 1.0JDK 1.5(为单线程优化而新增)
继承关系继承 AbstractStringBuilder,实现 CharSequence、Serializable、Comparable继承 AbstractStringBuilder,实现 Appendable 等继承 AbstractStringBuilder,实现 Appendable 等
方法同步无需同步大部分修改方法(如 append、delete)都是 synchronized无 synchronized
典型使用场景常量字符串、键值存储、配置信息多线程频繁拼接(如日志记录、共享缓冲)单线程频繁拼接(如 JSON 构建、循环拼接)——现代项目首选
toString() 实现返回自身(缓存优化 JDK 7+)新建 String 对象(调用 Arrays.copyOf)同 StringBuffer

2. 底层实现深入剖析

  • String 的不可变性

    // JDK 源码简化版
    public final class String {
        private final char[] value;  // final 修饰,不可重新赋值
        private final int hash;      // 缓存 hashCode
    }
    

    任何“修改”操作(如 concatreplace)都会 new String() 并复制 char[],原对象不变。

  • StringBuffer / StringBuilder 的可变性
    两者都继承自 AbstractStringBuilder

    abstract class AbstractStringBuilder {
        char[] value;      // 非 final,可扩容
        int count;         // 当前长度
    }
    
    • append 等操作直接操作 value 数组。
    • 扩容时:Arrays.copyOf 创建更大数组,复制旧内容。

    关键区别:StringBuffer 的公共方法加了 synchronized

    // StringBuffer 示例
    public synchronized StringBuffer append(String str) { ... }
    
    // StringBuilder 示例
    public StringBuilder append(String str) { ... }  // 无 synchronized
    

3. 性能对比实测(循环 10 万次拼接)

public class Test {
    public static void main(String[] args) {
        int times = 100000;

        // String
        long start = System.nanoTime();
        String s = "";
        for (int i = 0; i < times; i++) {
            s += i;
        }
        System.out.println("String 用时: " + (System.nanoTime() - start) / 1e6 + " ms");

        // StringBuilder
        start = System.nanoTime();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < times; i++) {
            sb.append(i);
        }
        System.out.println("StringBuilder 用时: " + (System.nanoTime() - start) / 1e6 + " ms");

        // StringBuffer
        start = System.nanoTime();
        StringBuffer sbf = new StringBuffer();
        for (int i = 0; i < times; i++) {
            sbf.append(i);
        }
        System.out.println("StringBuffer 用时: " + (System.nanoTime() - start) / 1e6 + " ms");
    }
}

典型运行结果(JDK 17,普通电脑):

  • String:约 3000~5000 ms(极慢,产生海量临时对象)
  • StringBuilder:约 10~20 ms
  • StringBuffer:约 15~30 ms(略慢于 Builder,因锁开销)

可见,频繁修改时 StringBuilder 性能遥遥领先。

4. 编译器优化小秘密

  • 单次 + 操作:JVM 会自动优化为 StringBuilder:

    String result = "a" + "b" + "c";  // 编译后相当于 new StringBuilder().append("a").append("b").append("c").toString()
    
  • 循环中 + 操作:不会跨循环优化,仍建议手动用 StringBuilder。

5. 选择指南(实战总结)

  1. 内容几乎不修改 → 用 String(最安全、支持常量池)。

  2. 多线程 + 频繁修改 → 用 StringBuffer(虽慢点但安全)。

  3. 单线程 + 频繁修改必须用 StringBuilder(性能最佳,99% 场景适用)。

  4. 已知长度大 → 提前指定容量,避免扩容:

    StringBuilder sb = new StringBuilder(10000);  // 预分配
    
  5. 现代替代方案:复杂场景可考虑 String.join()String.format() 或流式操作,但核心拼接仍推荐 StringBuilder。

6. 常见误区澄清

  • 误区:StringBuffer 完全过时了 → 错!在多线程共享同一缓冲时仍有价值。
  • 误区:StringBuilder 线程不安全就不能用 → 大多数业务是单线程,安全使用即可。
  • 误区:String 完全不能用于拼接 → 小量拼接没问题,大量必须避免。

总结

到此这篇关于Java中String、StringBuffer和StringBuilder底层实现的文章就介绍到这了,更多相关Java中String、StringBuffer和StringBuilder内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件的实例代码

    鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件的实例代码

    这篇文章主要介绍了鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Spring Cloud Feign组成配置过程解析

    Spring Cloud Feign组成配置过程解析

    这篇文章主要介绍了Spring Cloud Feign组成配置过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • springboot 场景启动器使用解析

    springboot 场景启动器使用解析

    这篇文章主要介绍了springboot 场景启动器使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Spring MVC 文件上传的示例代码

    Spring MVC 文件上传的示例代码

    本篇文章主要介绍了Spring MVC 文件上传的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • SpringBoot实现图形验证码的操作方法

    SpringBoot实现图形验证码的操作方法

    随着安全性的要求越来越高,目前许多项目中都使用了验证码,验证码也有各种类型,如 图形验证码、短信验证码、邮件验证码、人脸识别等,本文给大家介绍SpringBoot实现图形验证码的方法,感兴趣的朋友跟随小编一起看看吧
    2024-07-07
  • 关于Jar包部署命令全面解析

    关于Jar包部署命令全面解析

    这篇文章主要介绍了Jar包部署命令全面解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Simple Java Mail邮件发送实现过程解析

    Simple Java Mail邮件发送实现过程解析

    这篇文章主要介绍了Simple Java Mail邮件发送实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Java单元测试实践(Mock)

    Java单元测试实践(Mock)

    本文介绍了单元测试、JUnit、Spring相关注解、Mockito、断言库的使用方法,涵盖MockMvc、@Mock、@MockBean、@Spy、@InjectMocks、@ParameterizedTest、@CsvSource、@ValueSource、@MethodSource等,介绍了Mock的概念及用途,重点讲解了单元测试的步骤、MockMvc的使用
    2026-04-04
  • Mybatis模糊查询和动态sql语句的用法

    Mybatis模糊查询和动态sql语句的用法

    今天小编就为大家分享一篇关于Mybatis模糊查询和动态sql语句的用法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • java制作简单验证码功能

    java制作简单验证码功能

    这篇文章主要为大家详细介绍了java制作简单验证码功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11

最新评论