Java 中 String、StringBuilder、StringBuffer 有何区别?StringBuffer 还有用武之地吗?

简介: 前言开发项目时,我们通常会复用一些之前项目的代码,然而复用并不意味着应该直接复制粘贴。最近重构项目,发现项目中存在了很多未被使用的工具类、一些将自己封装的 ORM 类,错误使用访问权限修饰符等情况,想必是有同事直接复制了其他项目的代码,而其他项目代码质量又不佳,导致新项目代码中充斥着腐朽的味道。事实上,非业务逻辑的部分,大多数都有一些开源的框架、工具,它们可以帮助我们将注意力集中在核心的业务逻辑中。

前言


开发项目时,我们通常会复用一些之前项目的代码,然而复用并不意味着应该直接复制粘贴。最近重构项目,发现项目中存在了很多未被使用的工具类、一些将自己封装的 ORM 类,错误使用访问权限修饰符等情况,想必是有同事直接复制了其他项目的代码,而其他项目代码质量又不佳,导致新项目代码中充斥着腐朽的味道。事实上,非业务逻辑的部分,大多数都有一些开源的框架、工具,它们可以帮助我们将注意力集中在核心的业务逻辑中。然而即便是核心的业务逻辑,也需要我们具有扎实的基础。重构代码中,笔者留意到不少地方在方法内部的字符串拼接中使用了 StringBuffer,StringBuffer 作为多线程下使用的类在方法内部使用反而会影响性能,于是直接改为了 StringBuilder。


String 、StringBuffer 和 StringBuilder 作为 Java 中最基础的知识,每一位 Java 开发者都应该进行掌握,本篇姑且对其做一个总结,希望看到的小伙伴能够在合适的场景中使用这三者。


String


String 是 Java 对字符序列的抽象,Java 中使用基本类型 char 表示单个字符,使用 String 类表示字符序列,为了对字符串进行共享,Java 将 String 设置为不可变,类本身和用于保存字符序列的 char[] 类型的成员变量均使用 final 进行设置,因此,String 一经创建便不可修改,String 中用于操作字符串的方法都会产生新的对象。


由于 String 的不变性,String 在单线程环境和多线程环境均可使用而不会产生线程安全问题。但是由于每次对字符串本身进行操作都会产生新的对象,因此在拼接大量字符串时会产生大量的对象,占用了内存,对垃圾回收造成一定的影响,性能上会有一定的损耗,不适用大量拼接字符串的场景。


String 类部分代码如下。


public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
  private final char value[];
    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }
}


StringBuffer 和 StringBuilder


为了应对大量对字符串操作的场景,Java 同时提出了一个新的类 StringBuffer,StringBuffer 类在操作字符串的方法上都加了 sychronized 关键字,因此在多线程的情况下并不会有线程安全问题。由于其加了同步锁,所以性能上会相对较差。Java 5 时,为了解决性能问题,Java 又提出了一个新的类 StringBuilder,StringBuilder 的实现和 StringBuffer 相比基本相同,只是没有在方法上加 synchronized 关键字,因此不适用于多线程环境。Java 6 时,为了对对象锁进行优化,JDK 才添加 偏向锁、轻量级锁,这时在单线程下使用 StringBuffer 性能上则不会有较大的损耗。由于这两者实现基本相同,因此 StringBuffer 和 StringBuilder 具有相同的父类 AbstractStringBuilder,AbstractStringBuilder 底层和 String 相同,同样使用一个 char[] 数组保存字符序列,在操作字符串时操作的其内部的字符串序列而不会产生新的对象。String、StringBuffer 和 StringBuilder 的类图如下所示。


image.png


总结 StringBuffer 和 StringBuilder 如下。


StringBuffer 和 StringBuilder 具有相同的父类 AbstractStringBuilder。

StringBuffer 操作字符串的方法上添加了同步锁,适用于多线程,保证了线程安全,但性能较差。Java 6 以后在单线程使用性能上不会有较大损耗。

StringBuilder 操作字符串的方法上没有添加同步锁,因此只适用于单线程,性能上会相比 SringBuffer 稍有提高。


总结

总结 String、StringBuffer、StringBuilder 使用场景如下。


String:适用于较少情况对字符串本身进行操作的场景。

StringBuffer:适用于多线程下大量对字符串进行操作的场景,这种场景相对来说比较少。


StringBuilder:适用于单线程下大量对字符串进行操作的场景,大量字符串操作一般使用 StringBuilder 即可。


目录
相关文章
|
16天前
|
Java API 索引
Java基础—笔记—String篇
本文介绍了Java中的`String`类、包的管理和API文档的使用。包用于分类管理Java程序,同包下类无需导包,不同包需导入。使用API时,可按类名搜索、查看包、介绍、构造器和方法。方法命名能暗示其功能,注意参数和返回值。`String`创建有两种方式:双引号创建(常量池,共享)和构造器`new`(每次新建对象)。此外,列举了`String`的常用方法,如`length()`、`charAt()`、`equals()`、`substring()`等。
15 0
|
1天前
|
存储 缓存 Java
|
1天前
|
JavaScript 前端开发 Oracle
java和JavaScript的区别
java和JavaScript的区别
6 3
|
2天前
|
存储 编解码 算法
Java 的 String StringBuilder StringBuffer(上)
Java 的 String StringBuilder StringBuffer
23 0
|
17天前
|
移动开发 安全 Java
String、StringBuffer 、StringBuilder、StringJoiner
String、StringBuffer 、StringBuilder、StringJoiner
|
18天前
|
Java 关系型数据库 MySQL
大厂面试题详解:Java抽象类与接口的概念及区别
字节跳动大厂面试题详解:Java抽象类与接口的概念及区别
40 0
|
29天前
|
Java
java的 isEmpty 和 isBlank 区别?
java的 isEmpty 和 isBlank 区别?
8 0
|
1月前
|
Java
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
25 0
|
1月前
|
Java
Java String split()方法详细教程
Java String split()方法详细教程
23 0
|
1月前
|
安全 Java
Java StringBuffer 和 StringBuilder 类
Java StringBuffer 和 StringBuilder 类
16 0