StringBuffer源码分析

本文用于分析当创建StringBuffer对象后,调用append方法时,StringBuffer内部是如何扩容的

1、创建StringBuffer对象,并调用append方法

这是我们开发时经常做的

StringBuffer sb = new StringBuffer("abc");//原来数据的长度:3个字符
sb.append("defghijklmnopqrst");//新增加数据的长度:17个字符


2、查看append方法的源码

public synchronized StringBuffer append(String str) {
        super.append(str);
        return this;
    }

上面的代码可以知道它调用的是父类AbstractStringBuilder的append方法,接着进入父类的append方法

3、分析父类的append方法

//str-->"defghijklmnopqrst"
public AbstractStringBuilder append(String str) {
	//新增加的数据为null则直接返回字符串"null"
        if (str == null) str = "null";
        int len = str.length();//新增加数据的长度为:17
        ensureCapacityInternal(count + len);//扩容:count+len=3 + 17
        str.getChars(0, len, value, count);//将原来的数据复制到扩容后的数组中
        count += len;
        return this;
    }

从上面可以看出append方法调用了ensureCapacityInternal方法和str.getChars(0, len, value, count);,这里我们用3.1来分析前者(扩容操作),3.2来分析后者(将数据复制到扩容后的数组中)

 

===========================开始扩容=============================

3.1、ensureCapacityInternal()

//int minimumCapacity = 20
private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code:判断是否需要扩容,也就是说原来的capacity是否足够大
        if (minimumCapacity - value.length > 0) //20-19=1,1>0
            expandCapacity(minimumCapacity);
    }


上面的代码又调用了expandCapacity方法,我们用3.1下面的子标题来进行一步步分析

3.1.1 expandCapacity

void expandCapacity(int minimumCapacity) { //int minimumCapacity=20
        int newCapacity = value.length * 2 + 2; //新的容量capacity=原来的长度*2+2
	//扩容后的容量-字符串实际长度<0(就是说如果扩容后还装不下),
	//则使用字符串实际长度作为StringBuffer的capacity
	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);
    }


3.1.1.1 Arrays.copyOf(value, newCapacity)

//copyOf方法用于创建一个新数组,新数组的长度是扩容后的长度,并将原来的值复制到新的数组中
//这里需要注意,虽然数组是新的,但是StringBuffer还是原来的StringBuffer
//original:StringBuffer中原来的值,也就是'abc'
//newLength:新的长度,19*2+2=40
public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }


======================扩容结束======================

3.2 str.getChars(0, len, value, count);

 

将字符从str字符串复制到目标数组value中,这里就是把str的所有值复制到value数组的最后面

//int srcBegin:字符串str中要复制的第一个字符的索引
//int srcEnd:字符串str中要复制的最后一个字符之后的索引
//char dst[]:目标数组
//int dstBegin:目标数组中的起始偏移量
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);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值