1:定义
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
2:属性
static final long serialVersionUID = 3388685877147921107L;
3:构造函数
(1)构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。
public StringBuffer() { super(16); }
继承父类的AbstractStringBuilder的构造函数
AbstractStringBuilder(int capacity) { value = new char[capacity]; }
(2)构造一个不带字符,但具有指定初始容量的字符串缓冲区
public StringBuffer(int capacity) { super(capacity); }
(3)构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。该字符串的初始容量为 16 加上字符串参数的长度
public StringBuffer(String str) { //这个执行父类的带参构造函数AbstractStringBuilder(int capacity) super(str.length() + 16); append(str); }
append 是用 synchronized 修饰的,所以是线程安全的
public synchronized StringBuffer append(String str) { //执行父类的append(str) super.append(str); return this; }
父类 AbstractStringBuilder 的 append 方法
public AbstractStringBuilder append(String str) { if (str == null) str = "null"; int len = str.length(); ensureCapacityInternal(count + len);//扩大容量 str.getChars(0, len, value, count); count += len; return this; }
//扩大容量
private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code:判断是否需要扩容,也就是说原来的capacity是否足够大 if (minimumCapacity - value.length > 0) //20-19=1,1>0 expandCapacity(minimumCapacity); }
void expandCapacity(int minimumCapacity) { //新容量 原始容量 * 2 + 2 int newCapacity = value.length * 2 + 2; if (newCapacity - minimumCapacity < 0) //扩容后的容量-字符串实际长度<0(就是说如果扩容后还装不下), newCapacity = minimumCapacity; //则使用字符串实际长度作为StringBuffer的capacity if (newCapacity < 0) {//扩容后的容量超过integer的最大值 if (minimumCapacity < 0) // overflow //最终容量超过integer的最大值 throw new OutOfMemoryError(); newCapacity = Integer.MAX_VALUE; } //将旧的值剪切到新的字符数组。 value = Arrays.copyOf(value, newCapacity); }
4:常用方法
4.1 append 源码
(1)StringBuffer sb
public AbstractStringBuilder append(StringBuffer sb) { if (sb == null) return append("null"); int len = sb.length(); int newCount = count + len; if (newCount > value.length) expandCapacity(newCount); // 若value存储容量不够需扩容。扩容方法省略暂不分析,基本上根据Arrays.copyOf()方法,复制指定的数组,以使副本具有指定的长度。到头来copyOf的源码一样是利用arraycopy方法来复制数组和扩容 sb.getChars(0, len, value, count); //把sb的内容0->len复制到value中,注意value参数,此时的value是已经扩容后的value。 count = newCount; // 更新新count值 return this; }
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) // dstBegin就是原有count接下来的位置
{
if (srcBegin < 0)
throw new StringIndexOutOfBoundsException(srcBegin);
if ((srcEnd < 0) || (srcEnd > count))
throw new StringIndexOutOfBoundsException(srcEnd);
if (srcBegin > srcEnd)
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); //以上是Bound Check
System.arraycopy(value, srcBegin,dst, dstBegin, srcEnd - srcBegin); // 从指定源数组中复制一个数组
} //AbstractStringBuilder里定义的getChars方法体,是对System.arraycopy方法 + 边界检查的进一步封装而已。
(2)char[] str
public AbstractStringBuilder append(char[] str) { int len = str.length; //数组长度 ensureCapacityInternal(count + len); //扩容 System.arraycopy(str, 0, value, count, len); count += len; return this; }(3) 添加字符数组str从偏移量offset开始,长度为len的子数组。
public AbstractStringBuilder append(char str[], int offset, int len) { if (len > 0) // let arraycopy report AIOOBE for len < 0 ensureCapacityInternal(count + len); System.arraycopy(str, offset, value, count, len); count += len; return this; }
(4) boolean b
public AbstractStringBuilder append(boolean b) { if (b) { ensureCapacityInternal(count + 4); value[count++] = 't'; value[count++] = 'r'; value[count++] = 'u'; value[count++] = 'e'; } else { ensureCapacityInternal(count + 5); value[count++] = 'f'; value[count++] = 'a'; value[count++] = 'l'; value[count++] = 's'; value[count++] = 'e'; } return this; }(5)char c
public AbstractStringBuilder append(char c) { //字符的长度为 1 ,只需增加一个 ensureCapacityInternal(count + 1); value[count++] = c; return this; }
(6)int i
public AbstractStringBuilder append(int i) { if (i == Integer.MIN_VALUE) { append("-2147483648"); return this; } // stringSizeOfInt,判断输入的整数i占多少位,如负数+1,方法源码往后看。 int appendedLength = (i < 0) ? stringSizeOfInt(-i) + 1 : stringSizeOfInt(i); int spaceNeeded = count + appendedLength; if (spaceNeeded > value.length) // 检查容量,是否需扩容 expandCapacity(spaceNeeded); Integer.getChars(i, spaceNeeded, value); // 把整型i以字符的形式加进buffer(value)中 count = spaceNeeded; //更新count长度。 return this; }
//占位表 final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,99999999, 999999999, Integer.MAX_VALUE }; // Requires positive x static int stringSizeOfInt(int x) { for (int i=0; ; i++) if (x <= sizeTable[i]) // 无限循环将整型x与占位表逐一对比,例如x=100,将与占位表索引为2的999匹配。 return i+1; //返回2+1,占3位。 }
(7) long i
public AbstractStringBuilder append(long l) { if (l == Long.MIN_VALUE) { append("-9223372036854775808"); return this; } int appendedLength = (l < 0) ? Long.stringSize(-l) + 1 : Long.stringSize(l); int spaceNeeded = count + appendedLength; ensureCapacityInternal(spaceNeeded); Long.getChars(l, spaceNeeded, value); count = spaceNeeded; return this; }
// Requires positive x static int stringSizeOfLong(long x) { long p = 10; for (int i=1; i<19; i++) { if (x < p) // 与两位数10比较,小于返回占一位 return i; p = 10*p; //如此类推,小于100占2位 } return 19; // 最大19位 }4.2 delete
delete(int start, int end) 删除字符序列中从start开始,end结束的子序列
public AbstractStringBuilder delete(int start, int end) { if (start < 0) throw new StringIndexOutOfBoundsException(start); if (end > count) end = count; if (start > end) throw new StringIndexOutOfBoundsException(); int len = end - start; if (len > 0) { System.arraycopy(value, start+len, value, start, count-end); count -= len; } return this; }deleteCharAt(int index)
public AbstractStringBuilder deleteCharAt(int index) { if ((index < 0) || (index >= count)) throw new StringIndexOutOfBoundsException(index); System.arraycopy(value, index+1, value, index, count-index-1); count--; return this; }4.3 replace
public AbstractStringBuilder replace(int start, int end, String str) { if (start < 0) throw new StringIndexOutOfBoundsException(start); if (start > count) throw new StringIndexOutOfBoundsException("start > length()"); if (start > end) throw new StringIndexOutOfBoundsException("start > end"); // 以上都是一些Bounds Checking,没什么好说。 if (end > count) //若替换字符边界超出字符长度,把字符长度赋予边界量 end = count; int len = str.length(); //新字符长度,要加上替换长度,减去截取长度 int newCount = count + len - (end - start); if (newCount > value.length) //是否大于已有容量,是则扩容 expandCapacity(newCount); //复制数组,先预留替换字符串str的长度,看后面的解释。 System.arraycopy(value, end, value, start + len, count - end); str.getChars(value, start);//填充str到value,start索引开始 count = newCount; return this; }
4.4 insert 方法(其实跟replace差不多,都是先通过System.arraycopy Method在字符数组value中预留一个空间,再用多一次这方法插入str或char[]。)
(1)insert(int index, char str[], int offset,int len)
// StringBuffer里面,调用父类的方法 public synchronized StringBuffer insert(int index, char str[], int offset, int len) { super.insert(index, str, offset, len); return this; }
public AbstractStringBuilder insert(int index, char str[], int offset, int len) { // bounds checking if ((index < 0) || (index > length())) throw new StringIndexOutOfBoundsException(index); // 注意:offset的值,offset + len不应大于str.length if ((offset < 0) || (len < 0) || (offset > str.length - len)) throw new StringIndexOutOfBoundsException( "offset " + offset + ", len " + len + ", str.length " + str.length); int newCount = count + len; if (newCount > value.length) expandCapacity(newCount); // 从index开始,预留了长度为len的空间;从index+len开始,将长度为count-index的后半截补充。 System.arraycopy(value, index, value, index + len, count - index); // str字符串数组,从索引offset开始复制,长度为len,复制到以索引index位置的value字符串数组。 System.arraycopy(str, offset, value, index, len); count = newCount; //记得更新实际字符长度(字符数量)。 return this; }