Java中String,StringBuilder,StringBuffer三者的区别

本文详细对比了String、StringBuilder和StringBuffer在运行速度和线程安全性方面的区别。介绍了String不可变性的特点及其对性能的影响,同时分析了StringBuilder和StringBuffer作为可变字符串在性能上的优势,并指出了它们在线程安全上的不同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

String,StringBuilder,StringBuffer三者区别主要体现在两个方面,即运行速度和线程安全。


一.运行速度

  1. 运行速度比较
    StringBuilder > StringBuffer > String

  2. 原因分析
    a. String为字符串常量,String在设计的时候基于安全和性能的原因设置为final不可变,我们代码中对字符串的操作,实际上是重新new一个String对象返回,原来的对象没有引用会GC自动回收;

    b. StringBuilder和StringBuffer均为字符串变量,是可以更改的。

    以下面一段代码为例:

    String str = "hello ";
    System.out.println(str);
    
    str = str + "world";
    System.out.println(str);

    运行结果:
    先输出“hello ”,然后又输出“hello world”;

    说明:
    a. 结果好像是str这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str,并把“hello ”赋值给str,然后在第三行中,其实JVM又创建了一个新的对象也名为str,然后再把原来的str的值和“world”加起来再赋值给新的str,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。

    b. 而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。

  3. 另外说明
    String str = “hello ” + “world”;
    String str = “hello world”;

    这两种形式是完全一样的,java编译器有一个优化措施:
    当一个计算表达式参与运算的值都是字面量(直接量),那么直接计算,并将结果编译到.class文件中。

    但如果写成以下这种形式:
    String str1 = “hello “;
    String str2 = “world”;
    String str = str1 + str2;

    那么JVM就会像上面说的那样,不断的创建、回收对象来进行这个操作了。速度就会很慢。

二.线程安全

在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的。

如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。

三.总结一下

1、StringBuffer 与 StringBuilder 中的方法和功能完全是等价的;

2、只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的;

3、在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全而StringBuffer则每次都需要判断锁,效率相对更低。

### StringStringBuilder StringBuffer区别 #### 1. 可变性 - **String**: 表示不可变的字符序列。一旦创建,其内容无法更改。任何对 `String` 的操作(如拼接、替换)都会生成一个新的 `String` 对象[^5]。 - **StringBuilder** **StringBuffer**: 都是可变的字符序列容器。可以对其内容进行修改而不必每次都创建新对象[^4]。 #### 2. 线程安全性 - **String**: 因为其不可变特性,天然具备线程安全性[^5]。 - **StringBuffer**: 提供了线程安全的操作机制,通过在方法内部加入同步锁来实现。 - **StringBuilder**: 没有任何同步措施,因此不具备线程安全性,但在单线程环境下性能更高。 #### 3. 性能比较 - 在执行速度方面,三者的顺序通常是:`StringBuilder > StringBuffer > String`。 - 当涉及大量的字符串拼接操作时,`StringBuilder` `StringBuffer` 明显优于 `String`,因为后者每次操作都会创建新的对象[^2]。 #### 4. 使用场景 - **String**: 适合用于字符串内容较少变动的情况,例如常量定义或简单的字符串处理[^5]。 - **StringBuilder**: 推荐用于单线程环境下的高效字符串构建修改操作。 - **StringBuffer**: 更适合多线程环境中需要保证数据一致性的场合[^4]。 #### 示例代码 以下是三种类型的简单对比演示: ```java // String 示例 public class StringType { public static void main(String[] args) { String str = "Hello"; System.out.println(str.hashCode()); String str1 = str + "World"; // 创建了一个新的 String 对象 System.out.println(str1.hashCode()); } } // StringBuilder 示例 public class StringBuilderType { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.hashCode()); sb.append("World"); // 修改原有对象的内容 System.out.println(sb.hashCode()); } } // StringBuffer 示例 public class StringBufferType { public static void main(String[] args) { StringBuffer sbf = new StringBuffer("Hello"); System.out.println(sbf.hashCode()); sbf.append("World"); // 同样修改原有对象的内容 System.out.println(sbf.hashCode()); } } ``` 运行以上代码的结果表明,`StringBuilder` `StringBuffer` 在追加字符串时不改变原始对象的哈希码,而 `String` 则会因生成新对象而导致不同的哈希码[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值