String、StringBuffer和StringBuilder

String

String 是不可变类,被声明成 final class,它的所有属性都是 final 的。由于它的不可变的性质,所有的拼接、裁剪等字符串操作都会产生新的 String 对象。

StringBuffer

StringBuffer是为了解决字符串拼接、裁剪产生过多中间 String 对象的问题而提供的一个类(Java 1.5 新增)。可以采用 append() 或者 add() 方法将字符串添加到已有的字符串末尾或者指定位置。StringBuffer 保证了线程安全(所有的方法都添加了关键字 synchronized),也带来了额外的性能开销。若非有线程安全的必要,否则推荐使用 StringBuilder。

StringBuilder

StringBuilder 在能力上和 StringBuffer 没有任意差异,只是去掉了线程安全的部分(没有使用 synchronized 修饰)。

总结

String 是 immutable (不可变)的典型实现,原生的保证了基础线程安全,你无法对内部数据进行任何修改。由于不可变,String 对象在拷贝时不需要额外复制数据。

为了实现修改字符串序列的目的,StringBuffer 和 StringBuilder 底层都是利用可修改的 char(Java 9 以后是 byte)数组,这两个类都继承了 AbstractStringBuilder ,里面包含了基本操作。这个内部数组的长度是初始字符串的长度+16(没有输入字符串时,长度就是16)。

扩展思考--缓存

String 在 Java 6 以后提供了 intern() 方法,目的是提示 JVM 缓存对应的字符串,以备重复利用。在调用 intern() 方法时,如果已存在对应字符串则直接返回缓存里的实例,否则创建并缓存。在 Java 6历史版本中 ,intern() 方法缓存的字符串是放在了“永久代”(PermGen)中。这个空间有限,不会被 FullGC 之外的垃圾收集照顾到,操作不当容易引起 OOM。

在后续版本中 这个缓存被放置在堆中,避免了永久代被占满的问题。而在 Java 8中永久代被元数据区(MetaSpace)替代。并且缓存的大小在不断扩大,从最初的1009 到 7u40 版本的60013。

你可能感兴趣的:(String、StringBuffer和StringBuilder)