【Java基础】深入理解String、StringBuffer和StringBuilder的异同

一、结论:

String、StringBuffer和StringBuilder是Java中用于处理字符串的类,它们之间的区别主要体现在以下几个方面:

可变性String类是不可变的,一旦创建就不能修改,每次对字符串的操作都会创建新的字符串对象。而StringBuffer和StringBuilder类是可变的,可以在原字符串的基础上进行插入、删除和修改等操作。

线程安全性String类是线程安全的,因为它的不可变性使得多个线程不能同时修改同一个字符串对象。而StringBuffer类是线程安全的,所有方法都使用了synchronized关键字进行同步,可以在多线程环境下安全使用。而StringBuilder类是非线程安全的,没有进行同步处理,适用于单线程环境。

性能:由于String类的不可变性,每次对字符串进行修改操作都会创建新的字符串对象,会造成额外的内存开销。而StringBuffer和StringBuilder类支持原地修改字符串,避免了频繁创建对象的开销,因此在需要频繁进行字符串操作的场景下,StringBuffer和StringBuilder比String具有更好的性能。

一般来说,如果在单线程环境下进行字符串操作,且不需要频繁修改字符串内容,可以使用String类。如果在多线程环境下需要频繁修改字符串内容,并且要求线程安全,可以使用StringBuffer类。如果在单线程环境下需要频繁修改字符串内容,并且不要求线程安全,可以使用StringBuilder类以获得更好的性能。

以下将根据源码、对象创建多方面展示String、StringBuffer和StringBuilder的异同

可变性线程是否安全性能
String不可变线程安全最差,频繁修改String会创建大量垃圾对象
StringBuffer可变线程安全效率适中,因为方法加了synchronized,性能不是很好,但是保证了线程安全
StringBuilder可变线程不安全性能最好,但不保证线程安全

二、可变性

String(不可变)

String实例化的两种方式:
在这里插入图片描述
跟进String类看源码:
在这里插入图片描述
所以不管哪一种实例化的方式,所定义的字符串都会存在 value数组中,并且该字符数组被final关键字修饰,代表一旦赋值了,就不能修改了,也就代表了String类是不可变的

StringBuffer和StringBuilder(可变)

创建StringBuffer(或StringBuilder)对象,底层默认会创建一个长度为16的char数组
在这里插入图片描述在这里插入图片描述
StringBuffer、StringBuilder和String类似,底层也是用一个数组来存储字符串的值,并且数组的默认长度为16,即一个空的StringBuffer对象数组长度为16。实例化一个StringBuffer对象即创建了一个大小为16个字符的字符串缓冲区。但是​当我们调用有参构造函数创建一个StringBuffer对象时,数组长度就不再是16了,而是根据当前对象的值来决定数组的长度,数组的长度为“当前对象的值的长+16”。所以一个 StringBuffer 创建完成之后,有16个字符的空间可以对其值进行修改。如果修改的值范围超出了16个字符,会先检查StringBuffer对象的原char数组的容量能不能装下新的字符串,如果装不下则会对 char 数组进行扩容。

那StringBuffer是怎样进行扩容的呢?
扩容的逻辑就是创建一个新的 char 数组,将现有容量扩大一倍再加上2,如果还是不够大则直接等于需要的容量大小。扩容完成之后,将原数组的内容复制到新数组,最后将指针指向新的 char 数组。
说明用StringBuffer和StringBuilder创建的字符串对象的长度是可以动态可变的

三、线程安全性

String(线程安全)

实际上,String类是不可变的,因此它是线程安全的。多个线程可以同时读取String对象的值,而无需担心数据的一致性问题。

由于String类的不可变性,每次对字符串进行修改操作都会创建新的字符串对象,这意味着在频繁修改字符串的情况下可能会产生大量的临时对象,从而导致内存消耗较大。但是这并不涉及到线程安全性的问题。

StringBuffer(线程安全)和StringBuilder(线程不安全)

StringBuffer线程安全最大的体现就是在所有的方法体上加上了synchronized关键字
在这里插入图片描述
所以是线程安全的
相反StringBuilder的方法体上没有synchronized关键字,所以他是线程不安全的

四、性能

String(性能差)

由于String类的不可变性,每次对字符串进行修改操作都会创建新的字符串对象,会造成额外的内存开销。

StringBuffer(针对多线程)和StringBuilder(针对单线程)

  • StringBuffer和StringBuilder类支持原地修改字符串,避免了频繁创建对象的开销,因此在需要频繁进行字符串操作的场景下,StringBuffer和StringBuilder比String具有更好的性能。
  • 并且StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全,在多线程系统中可以保证数据同步,但是效率比较低;而StringBuilder 没有实现同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高。
  • 如果我们在实际开发过程中需要对字符串进行频繁的修改,不要使用String,否则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。

详细请参考,总结的很详细到位深入理解String、StringBuffer和StringBuilder

StringStringBufferStringBuilderJava中用于处理字符串的类。它们之间有以下异同: 1. String是不可变的,即一旦创建就不能修改。每次对String进行修改时,都会创建一个新的String对象。这使得String在多次修改时效率较低。而StringBuilderStringBuffer是可变的,可以直接修改字符串内容。 2. StringBufferStringBuilder都是可变的字符串缓冲区,可以进行插入、删除和修改等操作。它们提供了与String类似的API,但不保证线程安全。StringBuilder是在Java 5.0中引入的,与StringBuffer相比,StringBuilder不考虑同步锁的开销,因此在单线程操作下效率更高。而StringBuffer考虑了同步锁,因此在多线程环境下使用更安全。 3. 在使用场景上,如果在单线程环境下进行字符串操作,建议使用StringBuilder,因为它的效率更高。而在多线程环境下,为了保证线程安全,应该使用StringBuffer。 综上所述,StringStringBufferStringBuilder之间的主要区别在于可变性和线程安全性。String是不可变的,而StringBufferStringBuilder是可变的,StringBuilder的效率更高,但不保证线程安全,而StringBuffer考虑了线程安全。 #### 引用[.reference_title] - *1* *3* [StringStringBufferStringBuilder三者的异同](https://blog.csdn.net/m0_58052874/article/details/124385405)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [StringStringBufferStringBuilder异同点](https://blog.csdn.net/qq_54217349/article/details/126795527)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值