1.StringBuffer的构造函数
先来看看父类AbstractStringBuilder的构造函数,底层是一个字符数组来保存字符串的
AbstractStringBuilder(int capacity){
value=newchar[capacity];}
再来看看StringBuffer的构造函数
- 无参构造函数,默认容量为16
publicStringBuffer(){super(16);}
- 带参(参数为字符串)构造函数,默认容量为参数字符串长度加上16
publicStringBuffer(String str){super(str.length()+16);append(str);}
- 带参(参数为int容量)构造函数,容量大小为指定的大小
publicStringBuffer(int capacity){super(capacity);}
2.StringBuffer扩容
2.1原理:
- 如果新添加字符串(当然,append方法是重载的,添加其他类型的数据也可以,此处以字符串为例),导致原始的容量不够用,就会先进性扩容。
- 扩容的规则是:先 原始容量*2 + 2
- 1、如果扩容了之后,容量够用,新的容量就为扩容之后的容量。
- 2、如果扩容了之后,容量不够用,新的容量就是所需要的容量,即原始字符串长度加上新添加的字符串长度。
- 扩容完成之后,将原始数组复制到新的容量中,然后将新的字符串添加进去
2.2 代码
- StringBuffer的append方法,调用了父类的append方法
@Overridepublicsynchronized StringBufferappend(String str){
toStringCache= null;super.append(str);returnthis;}
- 父类的append方法,其中ensureCapacityInternal(count + len)方法就是判断是否需要扩容的方法,getChars方法是将新的字符串加到底层的原始字符数组中,偏移量为原始字符串的长度
public AbstractStringBuilderappend(StringBuffer sb){if(sb== null)returnappendNull();int len= sb.length();ensureCapacityInternal(count+ len);
sb.getChars(0, len, value, count);
count+= len;returnthis;}
- 再来看ensureCapacityInternal方法,如果所需要的最小长度大于了数组长度就得扩容,扩容方法为newCapacity(minimumCapacity)。扩容之后,就将原始数组复制到新容量中。
privatevoidensureCapacityInternal(int minimumCapacity){// overflow-conscious codeif(minimumCapacity- value.length>0){
value= Arrays.copyOf(value,newCapacity(minimumCapacity));}}
- 扩容方法newCapacity(int minCapacity),看代码注释
privateintnewCapacity(int minCapacity){// overflow-conscious code//value.length << 1就是将长度乘以2int newCapacity=(value.length<<1)+2;//如果新容量还是不够,就将需要的容量大小作为新的容量if(newCapacity- minCapacity<0){
newCapacity= minCapacity;}return(newCapacity<=0|| MAX_ARRAY_SIZE- newCapacity<0)?hugeCapacity(minCapacity): newCapacity;}
3.一个问题
请教一下广大网友:
既然StringBuffer是通过扩容和复制来完成的,而且Arrays.copyOf()方法完成之后,底层的数组地址值是会变化的。但是,为什么扩容和复制之后,字符串的地址值还是没有变化呢?