前言
JDK 8
String为不可变,StringBuilder、StringBuffer都为可变。
为什么String是不可变的?
// final修饰,禁止继承String
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
// final修饰数组,初始化后无法再次赋值
private final char value[];
...
}
StringBuilder、StringBuffer
两者都继承于AbstractStringBuilder
其中StringBuffer为线程安全,append操作会进行同步
// 用于缓存每次toString的值,当value被修改时置为null
private transient char[] toStringCache;
@Override
synchronized StringBuffer append(AbstractStringBuilder asb) {
toStringCache = null;
super.append(asb);
return this;
}
StrinBuilder, append操作不会同步
public StringBuilder append(String str) {
super.append(str);
return this;
}
下面我们来看他们的父类AbstractStringBuilder中的append方法。
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
// 保证数组能容纳新添加的数据,新长度超过原数组长度会做数组扩容。扩容后的容量为当前字符串长度
ensureCapacityInternal(count + len);
// 将str拼接到value数组中
str.getChars(0, len, value, count);
count += len;
return this;
}
append操作会先检查下数组的长度,保证数组能容下的字符。
// 存储的字符信息
char[] value;
// 保证数组的长度为
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
// 数组扩容
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}