Java 下 String、StringBuffer、StringBuilder 分析

Java 下 String、StringBuffer、StringBuilder 分析

String、StringBuffer、StringBuilder 常用于字符串处理,但是适用的场景各有不同。

先说结论。

共性

  1. 都是处理字符串的类。
  2. 三者都是 final 类,不允许被继承。生成的对象不可变更。

区别

内部数据(char)变更线程安全性说明
String数据不可变更安全数据本身是 final 封装的,对象本身不可改变,所以线程安全
StringBuffer数据可变更安全数据虽然可以变更,但是对外接口都加了同步锁,所以线程安全
StringBuilder数据可变更不安全数据可以变更,但是接口没有上锁,线程不安全

字符串常量池

字符串常量池 (String pool, String intern pool, String 保留池) 是 Java 堆内存中一个特殊的存储区域。

字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价。JVM 为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。

  1. 为了减少在 JVM 中创建的字符串的数量,字符串类维护了一个字符串池,每当代码创建字符串常量时,JVM 会首先检查字符串常量池。
  2. 如果字符串已经存在池中,就返回池中的实例引用。如果字符串不在池中,就会实例化一个字符串并放到池中。

Java 能够进行这样的优化是因为字符串是不可变的,可以不用担心数据冲突进行共享。

如代码:

String str1 = "Hello";
String str2 = "Hello";

内存分配

String

String 类型是为了利用已有的字符串数据(利用字符串常量池),降低资源消耗(heap 空间),需要 String 为 final 不可变的对象。

另外由于 String 对象不可变更,所以其 HashCode 只需生成一次,也就避免了后续的重新计算,提高了性能。

同时数据不可变更,也就保证了多线程访问的安全性。

缺点:

大量数据的操作是,会频繁生成 String 对象(改变对象引用),耗时严重。

StringBuffer

StringBuffer 对象是 final 的,但其对象的数据本身可以通过本身的接口,进行修改(修改本身而不是生成对象改变引用)。

StringBuffer 本身由于数据可变更,为了保证多线程访问下的安全性,接口都用 synchronized 加入同步锁保证线程安全。

因此在单线程下通过 StringBuffer 处理大量数据,也就有不必要的同步锁开销。

StringBuilder

StringBuilder 与 StringBuffer 类似,只是其接口不会加入任何线程安全的锁操作,显然是线程不安全的。

缺点:

多线程下操作线程不安全,需要手动加锁。

总结

不同场景下,建议使用不同的字符串处理对象。

String:少量数据的操作。

StringBuffer:多线程下操作大量数据。

StringBuilder:单线程下操作大量数据。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值