前言
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)); } }