StringBuffer与StringBulider分析
初始化分析
StringBuffer和StringBulider的初始化时,都定义了一个容量,这个容量在它们的变量还没有值的时候默认为16。
/**
* Constructs a string builder with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuilder() {
super(16);
}
它们的变量赋值的时候需要通过append方法追加字符串,在它们的源码中并没有给append方法定义实现方法,但是在它们的父类AbstractStringBuilder中有定义实现。
/**
* Appends the specified string to this character sequence.
* <p>
* The characters of the {@code String} argument are appended, in
* order, increasing the length of this sequence by the length of the
* argument. If {@code str} is {@code null}, then the four
* characters {@code "null"} are appended.
* <p>
* Let <i>n</i> be the length of this character sequence just prior to
* execution of the {@code append} method. Then the character at
* index <i>k</i> in the new character sequence is equal to the character
* at index <i>k</i> in the old character sequence, if <i>k</i> is less
* than <i>n</i>; otherwise, it is equal to the character at index
* <i>k-n</i> in the argument {@code str}.
*
* @param str a string.
* @return a reference to this object.
*/
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;
}
而从这个父类的构造方法中可以看到它们的底层存储是通过制定容量的字符数组实现的,而追加的字符串如果超过容量最大值,则会通过特定的方法再次计算扩容,这里字符串追加到数组的方法使用的native修饰的Arrays.copyOf(value,newCapacity(minimumCapacity))方法实现的。以下是jdk定义的扩容的方法实现。
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
这也就解释了为何以下这段代码获取到的stringbuffer变量的容量为34了。
StringBuffer sb = new StringBuffer();
sb.append("==================");
System.out.println(sb.capacity());
父类与接口
StringBuffer和StringBulider作为AbstractStringBuilder的子类,都是继承了AbstractStringBuilder类的。如果实例化一个StringBuffer对象如下:
AbstractStringBuilder asb = new AbstractStringBuilder();
接下来咱们看一下AbstractStringBuilder的常见方法:
方法 | 说明 |
---|---|
public int length() | 获取asb的长度 |
public int capacity() | 获取asb的容量 |
private void ensureCapacityInternal(int minimumCapacity) | 扩容asb的容量,大小为minimumCapacity |
public void setLength(int newLength) | 定义asb长度,空余的字符位置用’\0’代替 |
public char charAt(int index) | 获取asb指定索引的字符 |
public AbstractStringBuilder append(Object obj) | 追加obj的toString()到asb后面 |
public AbstractStringBuilder delete(int start, int end) | 删除指定开始结束索引的字符串 |
public AbstractStringBuilder replace(int start, int end, String str) | 在指定的开始结束字符串内用str替换 |
public String substring(int start, int end) | 截取指定位置的字符串 |
public AbstractStringBuilder insert(int index, char[] str, int offset,int len) | 在固定位置插入字符数组str |
public int indexOf(String str, int fromIndex) | 判断指定位置开始是否存在str,找不到则返回-1,这里调用string的indexOf方法 |
public abstract String toString() | 转换为string,这里不做实现,调用公共父类object的toString方法 |
以上的方法中,有部分方法有多个重载方法,比如append、insert等等,我这里只例举实现最具体的那个说明,还有部分不常见的方法未做例举。
实现了AbstractStringBuilder类的StringBulider和StringBuffer类自然就拥有以上这些方法,或沿用或重写,都是可以直接使用的。
与String一样,他们都实现了java.io.Serializable, CharSequence两个接口,所以底层的存储是通过字符数组实现的,它们也是可序列化的。
区别
StringBuffer与StringBulider几乎是非常相似的,无论是实现的接口还是继承的父类。
只不过特别的是在StringBuffer中有许多的方法是用synchronized修饰的,比如:indexOf、toString、writeObject、readObject、insert、substring、replace、delete、append、getChars、capacity、length等;也就是说这些方法是有线程锁存在的,即同一时间只能被调用一次。
最后,以上仅我个人分析所得小结,有问题还请善意指教,谢谢。