前言
了解一些java底层设计最直接最准确的的方法就是源码了。
StringBuffer和StringBuilder都继承自AbstractStringBuilder。jdk1.8中源码位于rt.jar/java/lang/
路径下。
相关源码
初始的空闲容量都是16,当调用append方法时调用的都是super.append即AbstractStringBuilder
中方法,所以扩容机制相同。
publicStringBuffer(){super(16);}publicStringBuffer(String str){super(str.length()+16);append(str);}publicStringBuilder(){super(16);}publicStringBuilder(String str){super(str.length()+16);append(str);}
通过append方法中的ensureCapacityInternal
方法可以看出当追加后超出容量会触发扩容,通过newCapacity
获得新容量。
privatevoidensureCapacityInternal(int minimumCapacity){if(minimumCapacity- value.length>0){
value=Arrays.copyOf(value,newCapacity(minimumCapacity));}}
计划扩容为2*n+2
,n为扩容前容量,如果追加后长度超出则扩容为n+count
,count为追加长度。由此可见下次append还会触发扩容机制。所以在设计时应该避免,最好能在初始时设置一个合理的容量。
privateintnewCapacity(int minCapacity){int newCapacity=(value.length<<1)+2;if(newCapacity- minCapacity<0){
newCapacity= minCapacity;}return(newCapacity<=0|| MAX_ARRAY_SIZE- newCapacity<0)?hugeCapacity(minCapacity): newCapacity;}
最大容量为Integer.MAX_VALUE
privateinthugeCapacity(int minCapacity){if(Integer.MAX_VALUE- minCapacity<0){thrownewOutOfMemoryError();}return(minCapacity> MAX_ARRAY_SIZE)? minCapacity: MAX_ARRAY_SIZE;}
另外还提供了方法用于用户测试调用的扩容方案,在追加超长字符串时可减少多次自动扩容的花销。
publicvoidensureCapacity(int minimumCapacity){if(minimumCapacity>0)ensureCapacityInternal(minimumCapacity);}
此外StringBuffer和StringBuilder的区别就在于StringBuffer的操作使用synchronized
关键字加了锁,是线程安全的。
结论
StringBuffer和StringBuilder扩容都是通过共同父类AbstractStringBuilder
实现的。
初始为len+16
或自设置。后续扩容k>2*n+2?k:2*n+2
。