String、StringBuffer、StringBuilder的区别

本文探讨了Java中String不可变性的原因,分析了String对象在追加操作时导致的内存浪费,并引出了StringBuilder和StringBuffer。StringBuilder适合单线程大量字符串操作,而StringBuffer在多线程环境下提供了线程安全性。通过对源码的分析,揭示了它们的内部机制和使用场景。
摘要由CSDN通过智能技术生成
  • String:我们对String都不陌生,相信大家也都知道String是不可变的,那么他为什么是不可变的呢?我们通过研究String的源码就不难发现String类已经被final修饰,并且它的 value[] 成员也被final修饰了,我们知道,String存取字符串是将他们一个一个的存到了字符数组里面,所以这也是最重要的String为什么是不可被修改的原因。
  • 拓展:final有哪些作用呢?final修饰的类不可被继承;final修饰的方法不可被重写;final修饰的常量不可被修改;在并发的时候,final也可以防止指令重排序
    在这里插入图片描述
  • 那么为什么会出现StringBuilder和StringBuffer呢?我们来看下面这段程序
public class Main {
    public static void main(String[] args) {
        String string = "";
        for(int i = 0; i < 10000; i++){
            string += "hello";
        }
    }
}

这句 string += “hello”;的过程相当于将原有的string变量指向的对象内容取出与"hello"作字符串相加操作再存进另一个新的String对象当中,再让string变量指向新生成的对象。我们通过反编译命令(javap -c Main),可以分析每次循环会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象。也就是说这个循环执行完毕new出了10000个对象,试想一下,如果这些对象没有被回收,会造成多大的内存资源浪费。

我们再看下面这段StringBuilder代码:

public class Main {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder();
        for(int i = 0; i < 10000; i++){
            stringBuilder.append("hello");
        }
    }
}

通过反编译命令我们可以分析出new操作只进行了一次,也就是说只生成了一个对象,append操作是在原有对象的基础上进行的。因此在循环了10000次之后,这段代码所占的资源要比上面小得多。

  • 那么我们弄清楚StringBuilder的出现之后,那么我们会想StringBuffer为什么会出现呢?我们阅读StringBuilder 和 StringBuffer 的源码不难发现,StringBuffer 比 StringBuilder 的成员方法中多了一个关键字 synchronized ,这意味着在多线程访问时起到了安全保护作用,也就是说StringBuffer是线程安全的。
  • StringBuilder部分源代码
    在这里插入图片描述
  • StringBuffer部分源代码
    在这里插入图片描述
总结
  • String:适用于少量的字符串操作的情况
  • StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
  • StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
  • .String对象不可变、StringBuffer对象可变的含义: 举个例子:String str = “aa”; str = “aa”+“bb”; 此时str的值为"aabb",但是"aabb"不是在开始的字符串"aa"后面直接连接的"bb",而是又新生成了字符串"aabb",字符串"aa"一旦被初始化,那么它的值不可能再改变了。 StringBuffer strb = StringBuffer(“aa”); strb.append(“bb”); 此时的strb的值也为"aabb",但是"aabb"是直接在开始的字符串"aa"后面连接的“bb”,并没有生成新的字符串。
  • String是个不可继承类(final修饰),也是个不可变类(内部char数组被final修饰)。
    StringBuffer和StringBuilder内部都是一般的动态数组,所以可变。StringBuilder是线程不安全的,而StringBuffer是线程安全的,因为方法基本都被synchronized修饰了。

参考大佬博客:探秘Java中的String、StringBuilder以及StringBuffer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值