【Java面试笔记:基础】5.String、StringBuffer、StringBuilder有什么区别?

1. String、StringBuffer 和 StringBuilder 的区别

String:

  • 不可变性:String 是不可变类,一旦创建,其内容不能被修改。任何对字符串的操作(如拼接、裁剪等)都会生成新的 String 对象。

    java 复制代码
    String str = "Hello";
    str += " World"; // 创建新对象,原对象仍为"Hello"
  • 线程安全:由于不可变性,String 是天然线程安全的。

  • 内存机制:字符串常量池复用相同值的字符串,节省内存。

  • 应用场景:适用于字符串内容不经常变化的场景,如常量声明、少量的字符串拼接操作等。

StringBuffer:

  • 可变性:StringBuffer 是可变的字符序列,允许在已有序列的末尾或指定位置添加字符串。

    java 复制代码
    StringBuffer sb = new StringBuffer("Hello");
    sb.append(" World"); // 直接修改原对象,无需创建新实例
  • 线程安全:StringBuffer 是线程安全的,通过在方法上加 synchronized 关键字实现线程同步。

    java 复制代码
    public synchronized StringBuffer append(String str) { ... }
  • 性能开销:同步锁导致多线程安全,StringBuffer 的性能开销较大。单线程下性能低于StringBuilder

  • 应用场景:适用于多线程环境下频繁进行字符串拼接的场景。

StringBuilder:

  • 可变性:StringBuilder 也是可变的字符序列,功能与 StringBuffer 类似。

    java 复制代码
    StringBuilder sb = new StringBuilder("Hello");
    sb.append(" World"); // 非同步操作,性能更高
  • 非线程安全:StringBuilder 去掉了线程安全机制,性能更高。单线程下比StringBuffer快约10%~15%

  • 应用场景:适用于单线程环境下频繁进行字符串拼接的场景,是进行字符串拼接的首选。

2. 字符串设计和实现考量

  • 不可变性:String 是典型的不可变类,所有属性都是 final 的,保证了线程安全。
  • 线程安全机制:StringBuffer 通过 synchronized 关键字实现线程安全,适合多线程环境。
  • 性能优化:StringBuilder 去掉了线程安全机制,减少了性能开销,适合单线程环境。
  • 内存占用:String 操作不当可能会产生大量临时对象,增加内存占用。

3. 字符串缓存

  • intern() 方法:String 提供了 intern() 方法,用于缓存字符串。如果字符串常量池中已经存在相同的字符串,则返回常量池中的实例;否则,将字符串放入常量池。
  • 字符串常量池:Java 6 以后,字符串常量池被放置在堆中,避免了永久代占满的问题。
  • G1 GC 下的字符串排重:JDK 8u20 之后引入了 G1 GC 下的字符串排重功能,通过 JVM 参数 -XX:+UseStringDeduplication 开启。

4. String 自身的演化

  • Compact Strings:Java 9 引入了 Compact Strings 设计,将字符串的存储方式从 char 数组改为 byte 数组加上编码标识,减少了内存占用。
  • 性能优化:Compact Strings 设计带来了更小的内存占用和更快的操作速度。

5. 编码相关问题

getBytes()String(byte[] bytes):这些方法隐含使用平台默认编码,可能导致乱码问题。建议在使用时明确指定编码方式。

6. 内存与设计考量

  • String常量池:相同值的字符串共享内存,适合重复使用。

    java 复制代码
    String s1 = "Java";
    String s2 = "Java"; // 复用常量池中的"Java"
  • StringBuilder/Buffer初始化:预估容量减少扩容次数。

    java 复制代码
    StringBuilder sb = new StringBuilder(1024); // 预设容量为1024

7. 使用场景总结

场景 推荐类 理由
字符串常量(如配置项) String 不可变性保证数据安全,常量池优化内存
单线程循环拼接字符串 StringBuilder 避免同步开销,性能最优
多线程共享字符串操作 StringBuffer 同步保证线程安全
SQL语句拼接、JSON生成 StringBuilder 单线程操作,高效且无需线程安全
相关推荐
挺菜的10 分钟前
【算法刷题记录(简单题)003】统计大写字母个数(java代码实现)
java·数据结构·算法
掘金-我是哪吒1 小时前
分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南
java·分布式·微服务·云原生·架构
亲爱的非洲野猪1 小时前
Kafka消息积压的多维度解决方案:超越简单扩容的完整策略
java·分布式·中间件·kafka
wfsm1 小时前
spring事件使用
java·后端·spring
微风粼粼2 小时前
程序员在线接单
java·jvm·后端·python·eclipse·tomcat·dubbo
缘来是庄2 小时前
设计模式之中介者模式
java·设计模式·中介者模式
rebel2 小时前
若依框架整合 CXF 实现 WebService 改造流程(后端)
java·后端
代码的余温3 小时前
5种高效解决Maven依赖冲突的方法
java·maven
慕y2743 小时前
Java学习第十六部分——JUnit框架
java·开发语言·学习
paishishaba4 小时前
Maven
java·maven