为什么要用StringBuilder?

195 阅读1分钟

内存维度

字符串,不管是String,还是字面量,其实都会创建新的对象。

而且,String类的所有方法,都会创建新的对象,也就是说,入参字符串本身是不改变的,但是出参字符串是会改变的,其实就是创建了一个新的对象,然后返回。

随便看一个方法的源码:java.lang.String#substring(int)

public String substring(int beginIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    int subLen = value.length - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); //会创建新的字符串对象
}

那为什么要用StringBuilder?

因为没有创建新的对象,其他都要创建新的对象,为什么sb就没有创建新的对象,看源码分析,其实就是先扩容数组,因为sb就是字符数组,然后再复制,注意目标数组的起点位置是原数组长度!所以,其实就是把新的字符串往后面拼接,没有创建新的对象!

看源码:java.lang.AbstractStringBuilder#append(char[])

public AbstractStringBuilder append(char[] str) {
    int len = str.length;
    //先扩容
    ensureCapacityInternal(count + len);
    //再复制
    System.arraycopy(str, 0, value, count, len); //注意第四个参数:其实就是从目标数组的起点位置开始复制
    count += len;
    return this;
}

System.arraycopy方法的源码注释说明: image.png


以上讲的其实就是内存维度,即为什么要用StringBuilder,而不是用+拼接字符串,特别是拼接非常多的情况下,就很费内存啊,就是这个原因。

同步维度

那为什么不用StringBuffered,因为StringBuffered是同步的啊,一般情况都没必要啊,所以实际中基本上都是用StringBuilder即可,只有八股文的时候,会问你一下两个有啥区别,这个就是同步维度。