String、StringBuffer、StringBuilder有什么区别

可变性

类都是被final修饰,不可以被继承
String类中,jdk8用 private final **char[]** value来保存字符串,jdk9用private final **byte**[] value来保存字符串,都用final修饰,所以String对象是不可变的。
StringBuffer和StringBuilder都继承AbstractStringBuilder,AbstractStringBuilder中用char[] value保存字符串,没有final修饰,所以这两个对象都是可变的。

线程安全

由于String对象不可变,所以是线程安全的。
StringBuffer对方法加了锁,所以是线程安全的。
StringBuilder没有加锁,所以是非线程安全的。

性能

String类型进行操作时,会产生新的对象
StringBuilder单线程时性能高
StringBuilder比StringBuffer性能大概高10%

字符串拼接的优化

提前预估字符串最终拼接大小,避免多次扩容造成性能损耗

在这里插入图片描述
利用不同版本的JDK进行编译

JDK8:
在这里插入图片描述
JDK9:
在这里插入图片描述
JDK8中字符串拼接操作会被优化成StringBuilder操作,JDK9中里面则是用了StringConcatFactory封装了统一的优化操作。

字符串的缓存

统计数据表明,堆中平均25%的对象是字符创,其中半数是重复的,所以通过建立缓存可以有效降低内存消耗和创建对象的开销。
String在JDK6之前**intern()**方法把字符创缓存,但是会缓存在永久代中,基本不会被垃圾回收,有可能会发生OOM,后续版本中,把这个放到了堆中,避免了永久代被占满的问题,甚至永久代在JDK8 中被MetaSpace替代了。
Intern是一种显式的排重机制,需要开发者写代码时候明确调用,不方便和效率问题,引出了G1 GC下的字符串排重,通过将相同数据的字符串指向同一份数据来做到,是JVM底层的改变。
字符串操作会利用到JVM的Intrinsic机制,运行特殊的本地代码。

String自身的演化

JDK历史用char数组存储,是两个bytes大小,拉丁语系语言的字符,不需要太宽的 char,造成了浪费,最终改为了byte数组加一个编码,通过的性能测试和产品试验,明显的看到紧凑字符串带来的占用内存小,更快操作速度的优势

注:
StringBuffer和StringBuilder的底层都是利用可修改的(char,jdk9之后是byte)数组,二者继承了AbstractStringBuilder,区别在于最终的方法是否加了synchronized

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值