StringBuilder 与 StringBuffer
类的定义
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
StringBuilder
和StringBuffer
类都使用final
关键字修饰,限制了该类无法被继承,里面的方法也无法被重写。这一点与String
类相同。
类的成员变量
abstract class AbstractStringBuilder implements Appendable, CharSequence {
// The value is used for character storage.
char[] value;
StringBuilder
和StringBuffer
类都继承了抽象类AbstractStringBuilder
- 其中,成员变量
value
用于存储字符串,与String
不同的是,该变量没有用final
修饰,因此是可变的
JDK 9 之后,变为
char[] value;
使用byte数组可以减少一半的内存,byte使用一个字节来存储一个char字符,char使用两个字节来存储一个char字符。只有当一个char字符大小超过0xFF时,才会将byte数组变为原来的两倍,用两个字节存储一个char字符。
append() 方法
public StringBuilder append(String str) {
super.append(str);
return this;
}
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
可以看出有两个区别:
StringBuffer
比StringBuilder
多了一个synchronized
修饰符,这是他俩最大的区别,StringBuffer
是线程安全的,而StringBuilder
不是。- 另外,
StringBuffer
比StringBuilder
多了一个toStringCache
字段
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
toStringCache
字段为StringBuffer.toString()
方法做缓存用,连续调用toString方法的时候由于这个字段的缓存就可以少了Arrays.copyOfRange
的操作。当StringBuffer
对象有修改时,这些修改的方法会先将toStringCache
字段设为null
。
他们都将 append
操作委托给了父类 AbstractStringBuilder
类的 append()
方法
public AbstractStringBuilder append(String str) {
if (str == null) {
return appendNull();
}
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
该方法会进行一下操作:
1、判断参数 str
是否为空指针,如果参数 str
是一个空指针的话,则会执行 appendNull()
方法,该方法会添加 'n','u','l','l'
四个字符,长度+4
2、进行容量确认,若容量不足时,会执行扩容操作,"旧容量 * 2 + 2",如果扩容之后仍不满足所需容量,则直接扩容至所需容量。
3、增加字符
StringBuilder
和StringBuffer
无参构造初始容量为16
;有参构造初始容量为str.length() + 16