String、StringBuilder和StringBuffer的比较

@

1.String特性

1.1 不可变

它是Immutable类,被声明为final class,所有属性也是final的, 其拼接、裁剪等操作都会产生新的String对象。不可变的主要作用在于当一个对象需要被多线程共享,并且访问频繁时,可以省略同步和锁等待的时间,从而大幅度提高系统性能。不可变模式是一个可以提高多线程程序的性能,降低多线程程序复杂度的设计模式。所以String是原生线程安全的。

1.2 字符串常量池

String在Java世界中使用过于频繁,队系统性能的影响权重很大,所以JVM有针对性的优化。为了节约内存空间,防止相同字符串反复出现,避免创建重读字符串,引入了缓存字符串常量池,其机制涉及到String的创建方式。

  1. 通过直接量给String对象引用赋值来创建一个字符串时,JVM首先检查池中是否有值相同的字符串对象,如果有则不需要创建直接从池中刚查找到的对象引用;如果没有则在池中新建字符串对象,返回对象引用,并且将新创建的对象放入池中。
  2. 采用new关键字新建一个字符串对象时,JVM首先检查池中有没有"xyz"这个字符串对象,如果有,则直接在堆中创建一个"xyz"字符串对象 ,不会把对象放入池中。如果没有,则首先在字符串池中创建一个"xyz"字符串对象,然后再在堆中创建一个"xyz"字符串对象
  3. Intern()方法。String提供了inter()显示方法提示JVM缓存字符串。 调用此方法后,如果池已经包含一个等于此String对象的字符串(equals(oject)),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。

String str1 = "123"; //通过直接量赋值方式,放入字符串常量池  
String str2 = new String(“123”);//通过new方式赋值方式,不放入字符串常量池

String s3 = new String("xyz");//通过new方式赋值方式,先在常量池创建xyz,再从堆中创建string对象,并将引用付给s3
String s4 = new String("xyz");//从堆中创建string对象,并将引用付给s4
System.out.println(s3==s4); //s3 != s4

2.StringBuilder和StringBuffer

两者都是实现AbstractStringBuilder抽象类,拥有几乎一致对外提供的调用接口。

2.1 区别

  1. String、StringBuilder和StringBuffer的在内存中的存储方式相同,不同点是StringBufer/StringBuilder对象的值是可以改变的,并且值改变以后,对象引用不会发生改变。
  2. 两者对象在构造过程中,首先按照默认大小申请一个字符数组,由于会不断加入新数据,当超过默认大小后,会创建一个更大的数组,并将原先的数组内容复制过来,再丢弃旧的数组。因此,对于较大对象的扩容会涉及大量的内存复制操作,如果能够预先评估大小,可提升性能。
  3. StringBufer是线程安全的,但是StringBuilder是线程不安全的。StringBufer类中方法定义前面都会有synchronize关键字加锁,性能要远低于StringBuilder。

2.2 应用场景

  1. 在字符串内容不经常发生变化的业务场景优先使用String类。例如:常量声明、少量的字符串拼接操作等。
  2. 如果有大量的字符串内容拼接,避免使用String与String之间的“+”操作,因为这样会产生大量无用的中间对象,耗费空间且执行效率低下(新建对象、回收对象花费大量时间)。
  3. 在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在多线程环境下,建议使用StringBufer,例如XML解析、HTTP参数解析与封装。运行在单线程环境下,建议使用StringBuilder,例如SQL语句拼装、JSON封装等。

参考
《Java核心技术36讲》
《深入理解JVM虚拟机》

StringStringBuilderStringBuffer是Java中用于处理字符串的三种类。 String是不可变的,也就是说一旦创建就不能被修改。每次对String进行操作(如拼接、替换)都会生成一个新的String对象,原始的String对象则会被丢弃。这使得在频繁操作字符串的情况下,会产生大量的临时对象,造成内存浪费。因此,当字符串不需要频繁修改时,可以使用String来提高性能。 StringBuilderStringBuffer是可变的字符串类,它们可以进行修改操作而不会创建新的对象。两者的主要区别在于线程安全性和性能上的差异。 StringBuffer是线程安全的,所有的方法都使用synchronized关键字进行同步,保证了多线程环境下的安全性。然而,这也导致了性能上的损失,因为同一时间只能有一个线程访问StringBuffer对象。 StringBuilder是非线程安全的,它的方法没有使用synchronized关键字进行同步。这使得在单线程环境下,StringBuilder的性能比StringBuffer更好。因此,如果在单线程环境下进行字符串操作,建议使用StringBuilder。 如果需要将StringBufferStringBuilder对象转换为String对象,有两种方法可以实现。一种是通过调用toString()方法,将其转换为String对象。另一种是通过String的构造器String(StringBuffer buffer)来创建一个新的String对象,该构造器会将StringBuffer的内容复制到新的String对象中。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [StringStringBufferStringBuilder类详解](https://blog.csdn.net/weixin_38568503/article/details/113794751)[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^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值