StringBuffer类原码解析

StringBuffer类用于字符串的拼接,由于它动态改变字符数组的长度并且事先会留有冗余长度,而不是像String拼接一样不断的重新创建新的String对象,所以速度上StringBuffer是快过String类的

从StringBuffer源码可以看到它是继承了AbstractStringBuilder类的,这个类暂时先不管他,我们主要看一下StringBuffer类的append方法

@Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

我们主要看参数为String类型的append方法,其余重载方法要么调用该方法要么也与其实现方式大同小异

先不管这个toStringCache参数,字面意思上可以大概知道该参数是用来做缓存的,我们从这个方法进入到其父类AbstarctStringBuilder的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;
    }

先看第一步,这里调用了appendNull方法,看看这个方法

    private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
    }

这个方法实际上就是拼接了“null”字符串,回到第二步,看实现字符数组长度适应的ensureCapacityInternal方法

private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

这个方法传入了一个最小长度,如果当前字符数组长度不够,便调用Arrays.copyOf方法改变value长度,看看这个方法

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;
    }

这个copyOf方法中创建了一个新的字符数组,并用arraycopy方法将原来数组的内容存了进行

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
代码解释:
  Object src : 原数组
   int srcPos : 从元数据的起始位置开始
  Object dest : 目标数组
  int destPos : 目标数组的开始起始位置
  int length  : 要copy的数组的长度   

将src数组从srcPos位置开始,复制长度为length的内容到dest数组,起始位置为destPos

 回到ensureCapacityInternal方法,可以看到它让value重新指向了这个新创建的字符数组从而实现了数组长度的变化

private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

 在看append方法的第三部,调用了String.getChars方法进行内容的拼接,而getChars在一系列校验之后最终是调用native层的getCharsNoCheck方法,

native void getCharsNoCheck(int start, int end, char[] buffer, int index) 
代码解释:   
    int start : 起始位置 
    int end : 终止位置   
    char[] buffer : 目标数组   
    int index : 目标数组的开始起始位置  

将该字符串从start到end的内容复制到buffer数组,起始位置为index

 于是再看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;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值