StringBuilder append方法源码分析



问题来源:在Java中,使用String str = “a" + "b" + “c"的时候,编译器会自动优化,使用StringBuilder来完成连接操作,那么,StringBuffer为什么比起String性能更高呢?

首先,以上字符串的连接,按照Java中字符串是常量不可更改的特性,理应是先有一个新的变量指向"a",而后再创建一个变量,指向"a + b",依次类推。但是按照这种方法,会产生很多没用的中间变量,严重影响了性能,所以实际中,编译器会自动创建StringBuilder优化性能。

StringBuilder中的append方法源码:

 @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

在AbstractStringBuilder中,数据是放在一个 char[ ] value的数组里的。 

由于StringBuffer继承自AbstractStringBuilder,所以查看父类的append方法:

 public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);		//这里传入的参数是增加字符串以后所需要的数组的最小长度
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
对该方法的进一步理解——ensureCapacityInternal()源码:

 /**
     * This method has the same contract as ensureCapacity, but is
     * never synchronized.
     */
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0)		//如果最小长度大于原来的数据长度,则扩容
            expandCapacity(minimumCapacity);
    }

    /**
     * This implements the expansion semantics of ensureCapacity with no
     * size check or synchronization.这里是扩容的具体实现
     */
    void expandCapacity(int minimumCapacity) {
        int newCapacity = value.length * 2 + 2;		//注意这里的扩容不是简单的用 原始长度 + 新字符串长度
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
        if (newCapacity < 0) {
            if (minimumCapacity < 0) // overflow
                throw new OutOfMemoryError();
            newCapacity = Integer.MAX_VALUE;
        }
        value = Arrays.copyOf(value, newCapacity);	//这里是通过Arrays的copyof方法,构造一个新的长度的数组,并把原来的数据拷贝进去
    }							//通过这样的方法,实现了数组的扩容
对该方法的进一步理解——String中的getChars方法:

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }
这个方法的目的是,从数组dst[ ]的dstBegin开始,将原始数据从srcBegin开始到srcEnd-1结束的字符串拷贝进来。此处String中的value,指的是String的原始字符串,即
调用这个方法的那个字符串。

以上,即为StringBuffer中append方法的完整过程

你可能感兴趣的:(Java)