首先他们底层都是调用父抽象类AbstractStringBuilder的,
主要区别在于StringBuffer是线程安全调用的方法都加了synchronized。
下面看一下AbstractStringBuilder的源码
abstract class AbstractStringBuilder implements Appendable, CharSequence {
//用来存储元素 注意是非final的所以可以被修改引用;
char[] value;
//用来统计上述存储元素的元素中存储了多少个元素
int count;
//子类调用时默认大小是16,如果是有参则是要添加的字符串的长度+16
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
//子类调用的append方法
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);//确保value.length()>count+str.length()
str.getChars(0, len, value, count);//调用要添加的字符串的getChars;
//把str的元素复制到该对象的value数组里去;
count += len;
return this;
}
}
StringBuffer和StringBuilder的append过程
- 初始化父类用来存储元素的char类型数组(char [] value)
- 确保原数组容量足够 (父类中有一个变量为 int count 记录目前已经存储的元素)
- 调用要添加字符串的getChars 把要添加的字符串字符数组复制到StringBuilder对象的value数组中去
注意 StringBuffer原理是相同的,无非StringBuffer是线程安全的,append方法中加了synchronized;
所以在多线程下使用StringBuffer.append来拼接字符串;
StringBuffer跟StringBuilder的除了线程安全之外,StringBuffer有一个
private transient char[] toStringCache; 用来缓存最后一次调用toString()返回的字符串,
这个缓存会在修改StringBuffer的方法调用时被清空;
StringBuffer和Stringbuilder和String的区别
- String是不可变的对象;String的拼接实际上是生成了新的字符串对象指向了同一个引用,而不是String被修改;StringBuffer和StringBuilder是可变的,经常用来拼接字符串;
- StringBuffer是线程安全的(因为加synchronized效率低一些), StringBuilder线程不安全但是效率高 使用"+"号拼接字符串底层就是创建了StringBuilder对象来拼接字符串,
- 在for循环中一个循环就会创建一个StringBuilder对象,所以在for循环中要显示使用StringBuilder或者StringBuffer来拼接字符串;而不是用“+”号来拼接;