三个都用来处理字符串,核心区别在于可变性和线程安全

  • string是不可变的,底层的char数组被final修饰,一旦创建就定死了,每次拼接、替换都会生成新对象
  • StringBuffer 和StringBuilder都是可变的,底层用一个可扩容的数组存字符,区别在于StringBuffer 的方法都加了synchronized 是线程安全的(都加在方法上)
  • StringBuilder没加锁,单线程下性能更好。

如何选择:

  • 字符串基本不变,或者只是少量凭接,直接用String
  • 多线程环境下要频繁修改字符串,用 StringBuffer
  • 单线程下大量拼接操作,用 StringBuilder

StringBuilder底层实现

继承自AbstractStringBuilder,核心就是一个char数组加一个count变量记录实际字符数

abstract class AbstarctStringBuilder{
    char[] value; // jdk 9 之前
    int count; // 实际字符数
}

append 操作先检查容量够不够,不够就扩容,然后把新内容拷贝到数组末尾,更新count,整个过程没有创建新对象

扩容策略是原容量*2 +2,如果还不够就直接扩到需要的大小

,扩容要创建新数组,拷贝旧数据,开销大,创建时最好预估一下最终长度,使用带参构造函数知道初始容量

(+2主要是为了处理边界情况,如果当前容量是0,×2还是0,+2后至少有2个位置,另外+2能让小容量扩容时多一点缓冲,减少频繁扩容次数)