写点什么

【Java】中的 String、StringBuffer 和 StringBuilder 的区别

作者:秋名山码民
  • 2022 年 7 月 11 日
  • 本文字数:1524 字

    阅读完需:约 5 分钟

String

在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。


需要注意的是,String 的值是不可变的,这就导致每次对 String 的操作都会生成新的 String 对象,这样不仅效率低下,而且大量浪费有限的内存空间。


至于为啥是不可变,我们可以来看下面这个图,发现 String 是用 final 修饰的,导致了他的不可变。



接下来我们从内存的角度来看一下,操作 String 类型时候的内存变化



不难看出:初始 String 值为"Hello",然后在这个字符串后面加上新的字符串"world",这个过程重新在堆中开辟了空间,操作这俩个字符串开辟了 3 次内存空间,为了解决**经常性字符串相关的操作,**引入了 StringBuilding 和 StringBuffer

StringBuilding 和 StringBuffer 的区别

其实这个问题一直在面试中问,那么为啥要问这么简单的问题呢?


其实这个一般只会在刚开始时候问,因为这个问题就是与线程安全有关,然后问怎么去保证线程安全?各种各样的锁,什么是锁,锁的机制,什么是死锁之类的问题,然后到 synchronized,他的原理,怎么使用,synchronized 和 volatile 区别是什么,为什么用 volatile,上升到 Java 内存模型,然后并发包…………,所以说面试这个过程,首先要抛出一个问题,然后根据你的状态,进行循序渐进,那么我们现在就来看这个最简单的问题吧!


与 String 类不同的是,StringBuffer 和 StringBuilding 类的对象可以被多次修改,而不产生新的对象


StringBuilding 类在 Java5 中被提出,他与 StringBuffer 最大的不同在于他不是线程安全的,即是不支持同步访问。 有得必有失,StringBuilding 由于不需要对应的锁机制(下面会提到),所以**其速度会更快一点,**在一般情况下我们更推荐使用 StringBuilding,但是应用程序在要求线程安全的情况下,则必须使用 StringBuffer 类型

关于字符串中的==

//1String s1=new String("Hello world");            String s2=new String("Hello world");      System.out.println(s1==s2);  // false       //2String s3="Hello world";    String s4="Hello world";  System.out.println(s3==s4);  // true
复制代码


代码 1 中局部变量 s1,s2 中存储的是 JVM 在堆中 new 出来的两个 String 对象的内存地址。虽然这两个 String 对象的值(char[]存放的字符序列)都是"Hello world"。 因此"=="比较的是两个不同的堆地址。


代码 2 中局部变量 s3,s4 中存储的也是地址,但却都是常量池中"Hello world"指向的堆的唯一的那个拘留字符串对象的地址 。自然相等了。

StringBuffer 与 StringBuilder 的线程安全性问题

这两者的方法没有很大区别。但在线程安全性方面,StringBuffer 允许多线程进行字符操作。这是因为在源代码中 StringBuffer 的很多方法都被关键字 synchronized 修饰了,而 StringBuilder 没有。


StringBuffer



StringBuilding



synchronized 的含义:


synchronized详解

效率问题

StringBuffer 和 StringBuilder 可谓双胞胎,StringBuilder 是 1.5 新引入的,其前身就是 StringBuffer。StringBuilder 的效率比 StringBuffer 稍高,如果不考虑线程安全,StringBuilder 应该是首选。另外,JVM 运行程序主要的时间耗费是在创建对象和回收对象上。

总结

  1. 在编译阶段就能够确定的字符串常量,完全没有必要创建 String 或 StringBuffer 对象。直接使用字符串常量的"+"连接操作效率最高。

  2. StringBuffer 对象的 append 效率要高于 String 对象的"+"连接操作。

  3. 不停的创建对象是程序低效的一个重要原因。那么相同的字符串值能否在堆中只创建一个 String 对象那。显然拘留字符串能够做到这一点,除了程序中的字符串常量会被 JVM 自动创建拘留字符串之外,调用 String 的 intern()方法也能做到这一点。当调用 intern()时,如果常量池中已经有了当前 String 的值,那么返回这个常量指向拘留对象的地址。如果没有,则将 String 值加入常量池中,并创建一个新的拘留字符串对象。

发布于: 刚刚阅读数: 4
用户头像

卷不死,就往…… 2021.10.19 加入

2019NOIP退役成员,华为云享专家,阿里云专家博主,csdn博主,努力进行算法分享,有问题欢迎私聊

评论

发布
暂无评论
【Java】中的String、StringBuffer和StringBuilder的区别_Java’_秋名山码民_InfoQ写作社区