Java 下 String、StringBuffer、StringBuilder 分析

版权声明:转载请写明出处,谢谢! https://blog.csdn.net/wilson1068/article/details/88246481

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:单线程下操作大量数据。

猜你喜欢

转载自blog.csdn.net/wilson1068/article/details/88246481