三者异同
String:不可变序列
StringBuffer:可变的字符序列,线程安全,效率低
StringBuilder:(jdk5.0)可变的字符序列,线程不安全,效率
都是用char[]存储
效率:StringBuilder>StringBuffer>String
源码分析:
String:String str=new String//char[] value=new char(0);
StringBuffer:
public StringBuffer() {
super(16);
}
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
底层创建了长度比实际字符串大16的数组通过append添加,且底层都是同一个数组,以此达到可变长字符串。这是最大长度,不是实际长度,length返回的count是实际长度。
StringBuffer与StringBuilder扩容问题:
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();//先判断是否为空
int len = str.length();//获取添加字符串长度
ensureCapacityInternal(count + len);//扩容
str.getChars(0, len, value, count);//将数组都复制到新数组中,底层调用了非java代码
count += len;//将当前长度保存在count中
return this;//返回新数组
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)//添加后的长度大于当前长度则进行扩容
expandCapacity(minimumCapacity);
}
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;//2倍+2
if (newCapacity - minimumCapacity < 0)//新的容量还是不满足那就直接用minimumCapacity当做新的容量
newCapacity = minimumCapacity;
if (newCapacity < 0) {//int数据有范围如果超过就会变成负数,那就直接报错
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);//使用Arrays工具类将最后获得的长度赋给value完成扩容
}
实际开发可以调用
public StringBuffer(int capacity) {
super(capacity);
}
自己指定长度,减少扩容操作,提高性能。StringBuffer与StringBuilder继承了同样的类,扩容机制一样。



