详细说明String、StringBuilder、StringBuffer的区别和联系

40 篇文章 3 订阅
5 篇文章 0 订阅

String、StringBuilder、StringBuffer的区别和联系

1、String的优点和缺点

说起String的缺点,可能大家一开始就会想到它的不可变O(∩_∩)O,但是说到String的优点,可能就有点想不起来了😆。其实它的优点也在于它的不可变。所以我们本节主要了解String为什么不可变,以及不可变的好处。

注意一般我们说的String不可变,都是使用双引号创建的String对象不可变

String的不可变主要有以下两个点

  1. final修饰。String类的底层是使用数组实现的,而该数组是使用final修饰的,导致我们无法进行重新赋值
  2. private修饰。String类的底层实现该数组是使用private修饰,同时String类没有向外部提供操作它的方法

image-20220806080408673

  • 不可变的优点

    • 能够使用常量池。由于String的不可变性,我们无法修改String对象的值,这就能够让我们安心使用常量池了。

      String使用双引号创建的对象被存放在常量池中,常量池中的的对象会被很多其它对象引用,假如是可变的,当我们改变String对象的值时,就会影响其它引用了,从而导致大量数据错误

    • 能够复用哈希码

      哈希码是根据对象地址进行创建的,地址不变,哈希码就不会变。当我们计算了对象的哈希码时,会将其缓存,由于地址不会变,所以再次使用就能够直接使用而无需计算

    • 线程安全。不可变就意味着在多线程下使用,不会影响到其它线程的正常运行。

  • 不可变的缺点

    • 占用内存。当我们在使用String对象是,每次进行字符串的修改,都会重新创建一个新的String对象,很废内存。
    • 不够灵活。因为String对象比较原始,操作字符串的API相对而言不够强大,有时想要操作字符串需要写很长的代码。

2、StringBuilder和StringBuffer的区别

相同点:

  1. 所属家族相同,都属于AbstractStringBuilder类的子类 ,且都在Java.lang包下

    image-20220806073837695

  2. 主要功能相同,都是用来优化对字符串的操作的。

    传统的使用+进行字符串拼接会大大增加常量池的压力,比如:

    String st = "a";
    String st += "b";
    

    上面两行代码就在常量池中创建了三个字符:a、b、ab;而使用StringBuffer或StringBuilder就能避免这种情况的发生,同时它们还提供了很多好用的API用于简化操作字符串。

  3. 底层原理相同,都是调用父类的方法创建一个初始容量为16byte[]数组。

    image-20220806075120279

    StringBuilderStringBuffer底层原理都是是创建一个初始容量为16的byte[]数组,该数组没有被final修饰,当容量超标时就会重新创建一个新的数组进行扩容,先将原来数组的内容拷贝到新数组中,然后让String Buffer的指针(准确来说是对象的引用)从指向开始的数组变为指向扩容后的数组,开始的数组就会被垃圾回收器给回收。

不同点:

  1. 适用场景不同Stringbuffer适用于多线程,StringBuilder适用于单线程。

    Stringbuffer对象中所属有的方法都有synchronized关键字修饰,都是同步方法,能够避免多线程下同时使用StringBuffer对象产生的线程安全问题;而StringBuilder对象中的方法都是普通方法,存在线程安全。

  2. 性能不同StringBuilder的性能高于StringBuffer

    由于StringBuffer的所有方法都是同步方法,每次调用,都需要进行上锁、解锁, 大大降低了性能。


拓展

  • 如何优化StringBuffer的性能

    在使用StringBuffer时,可以预估一下字符串的容量,然后在初始化时指定一个稍微大一点容量的StringBuffer对象。


总结

image-20220806091818474

类型特点适用场景
String不可变,线程安全操作少量数据或者不需要操作数据1
StringBuilder可变,线程不安全需要频繁操作数据且不用考虑线程安全
StringBuffer可变,线程安全,性能较低需要频繁操作数据且需要考虑线程安全

总的来讲String、StringBuilder、StringBuffer虽然是一步一步优化过来的,但是鱼与熊掌不可兼得,优化了这个问题又随之出现另一个问题,所以没有一个是完美的,也没有一个是能够取代其它任意一个的位置的,它们各司其职。我们要做的就是能够利用它们的特点解决某一类型的问题😄


推荐阅读:JavaSE知识【回顾+总结】


  1. 不需要操作数据的含义,就是简单的将String对象当作一个容器 ↩︎

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知识汲取者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值