Java语言中StringBuffer扩容问题

1.StringBuffer的构造函数

先来看看父类AbstractStringBuilder的构造函数,底层是一个字符数组来保存字符串的

AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

再来看看StringBuffer的构造函数

  • 无参构造函数,默认容量为16
public StringBuffer() {
        super(16);
    }
  • 带参(参数为字符串)构造函数,默认容量为参数字符串长度加上16
public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
  • 带参(参数为int容量)构造函数,容量大小为指定的大小
public StringBuffer(int capacity) {
        super(capacity);
    }

2.StringBuffer扩容
2.1原理:
  • 如果新添加字符串(当然,append方法是重载的,添加其他类型的数据也可以,此处以字符串为例),导致原始的容量不够用,就会先进性扩容。
  • 扩容的规则是:先 原始容量*2 + 2
    • 1、如果扩容了之后,容量够用,新的容量就为扩容之后的容量。
    • 2、如果扩容了之后,容量不够用,新的容量就是所需要的容量,即原始字符串长度加上新添加的字符串长度。
  • 扩容完成之后,将原始数组复制到新的容量中,然后将新的字符串添加进去
2.2 代码
  • StringBuffer的append方法,调用了父类的append方法
@Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
  • 父类的append方法,其中ensureCapacityInternal(count + len)方法就是判断是否需要扩容的方法,getChars方法是将新的字符串加到底层的原始字符数组中,偏移量为原始字符串的长度
    public AbstractStringBuilder append(StringBuffer sb) {
        if (sb == null)
            return appendNull();
        int len = sb.length();
        ensureCapacityInternal(count + len);
        sb.getChars(0, len, value, count);
        count += len;
        return this;
    }
  • 再来看ensureCapacityInternal方法,如果所需要的最小长度大于了数组长度就得扩容,扩容方法为newCapacity(minimumCapacity)。扩容之后,就将原始数组复制到新容量中。
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }
  • 扩容方法newCapacity(int minCapacity),看代码注释
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        
        //value.length << 1就是将长度乘以2
        int newCapacity = (value.length << 1) + 2;
        
        //如果新容量还是不够,就将需要的容量大小作为新的容量
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }
3.一个问题

请教一下广大网友:
既然StringBuffer是通过扩容和复制来完成的,而且Arrays.copyOf()方法完成之后,底层的数组地址值是会变化的。但是,为什么扩容和复制之后,字符串的地址值还是没有变化呢?

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值