先来看看各自都是如何存储的数组
StringBuffer继承自AbstractStringBuilder,自身没有定义存储的容器,而是继承了其父类的容器bash
这个就是StringBuilder存储字符的地方ui
从上面看出,String的字符是存储在一个被final修饰的char数组(相似于c中的指针常量)中的,而StringBuilder的字符是存储在一个普通的char数组中的spa
<hr>指针
这两个相加的操做能够看做这样code
final char c1[] = {'第','一','个','字','符','串'};
final char c2[] = {'第','二','个','字','符','串'};
final char c3[] = new char[12];
c3[] = {'第','一','个','字','符','串','第','二','个','字','符','串'};
c1 = c3;
//这段只作理解复制代码
String在运算的时候都会建立一个大小合适的char数组[],因此当下次再拼接的时候都要进行从新分配.cdn
StringBuilder特征blog
StringBuilder初始化容量是16(无参构造)继承
追加以前会计算一次容量,大于所需容量则会从新建立一个char[]数组,计算规则是 newCapacity = (value.length << 1) + 2; 也就是 原来长度*2+2内存
StringBuilder在运算的时候每次会计算容量是否足够,若是所需容量不小于自身容量,那么就会从新分配一个自身容量两倍+2的char[].因此省去了不少建立char[]的次数.
String之因此慢是由于,大部分cpu资源都被浪费在分配资源,拷贝资源的部分了,相比StringBuilder有更多的内存消耗.
StringBuilder快就快在,相比String,他在运算的时候分配内存次数小,因此拷贝次数和内存占用也随之减小.
因为GC的机制,即使原来的char[]没有引用了,那么也得等到GC触发的时候才能回收,String运算过多的时候就会产生大量垃圾,消耗内存.
若是目标字符串须要大量拼接的操做,那么这个时候应当使用StringBuilder.
反之,若是目标字符串操做次数极少,或者是常量,那么就直接使用String.