StringBuilder和StringBuffer
StringBuilder和StringBuffer都是抽象类AbstractStringBuilder的实现类,抽象类ASB实现了大部分的核心功能,最主要的append方法,是在ASB中写好的,子类中append基本都是调用此方法。
StringBuffer和StringBuilder的功能基本一致,可以说StringBuffer是StringBuilder的同步版本。
看一下ASB。
AbstractStringBuilder
定义和基本属性
实际上StringBuilder,是String类的可变版本,它低层也是char数组,像ArrayList类一样动态扩容,只是这个数组没有被限制修改,也没有final限定符,String类的“修改”是指向新的字符串,StringBuilder的修改就是直接修改低层char数组。
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
/**
* This no-arg constructor is necessary for serialization of subclasses.
*/
AbstractStringBuilder() {
}
/**
* Creates an AbstractStringBuilder of the specified capacity.
*/
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
// ...
}
Append方法
- append怎么实现的
看下SB的核心使用方法append,ASB一共重载了14个append方法,最核心的差不多是这个:
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
// 检查char数组是否需要扩容
ensureCapacityInternal(count + len);
// 使用了String类的char数组拷贝,把要追加的str copy到value的后面(以count为beginIndex)
str.getChars(0, len, value, count);
count += len;
return this;
}
所以append的实现就是把新的字符串的char数组的元素,放到原来数组里面。这个放置动作,是借助System.arraycopy方法。
看下ASB是如何动态扩容的:
/**
* This implements the expansion semantics of ensureCapacity with no
* size check or synchronization.
*/
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}
可以看到最后一句,把value指向新的数组,(这也是为什么value变量没有使用final的原因)。
对于String类来说,String的value是final的,String类的char数组不能动态扩容。一次初始化的字符串就是贯穿它的生命周期的长度,往后的“修改”都是创建的新的String对象返回的。String类对象不可变是因为内部char数组没有开放修改一定要牢记心中。
ArrayList(基于对象数组)的动态扩容,也是使用的数组copy(Arrays.copyOf)。
- append null
ASB是支持append null的,而且它的处理方法是直接追加{'n','u','l','l'}数组:
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
insert方法
insert方法低层实现是对数组的copy操作。
public AbstractStringBuilder insert(int index, char[] str, int offset,
int len)
{
if ((index < 0) || (index > length()))
throw new StringIndexOutOfBoundsException(index);
if ((offset < 0) || (len < 0) || (offset > str.length - len))
throw new StringIndexOutOfBoundsException(
"offset " + offset + ", len " + len + ", str.length "
+ str.length);
ensureCapacityInternal(count + len);
System.arraycopy(value, index, value, index + len, count - index);
System.arraycopy(str, offset, value, index, len);
count += len;
return this;
}
StringBuilder和StringBuffer
StringBuffer和StringBuilder,实现了ASB,前者线程安全,后者不是。
二者在实现时基本是调用super方法,核心都在ASB里面了。
网友评论