String和StringBuffer/StringBuilder之间为什么我们拼接字符串的时候会使用后者?

本文详细解析了String与StringBuilder在Java中的实现原理,探讨了final关键字的限制与StringBuilder的高效拼接机制,揭示了为何在大量字符串操作时,StringBuilder成为更优选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先咱们来看两个例子:

第一种情况报错了,但是第二种没有,同样是定义为final的对象,而String不能改变,但是StringBuilder却可以通过append改变,关于这个final关键字实际上它所谓的不可改变只是说我这个变量名对应着这个变量不可改变,这个变量名不能去对应别的变量,但是实际上存在于堆空间的变量是可以改变的,但是为什么定义为final的String拼接就不可以了呢?

原因很简单:

String这个类在jdk中定义的时候就是final的,这个类不能被继承改动,由于它是final的,所以我们不能改变它,那么就意味着在拼接字符串的时候我们直接产生新的String对象,那么就违背了这个final关键字,所以报错了

 

好,接下来说重点,为什么我们在进行大量字符串拼接的时候为什么不会使用String这个原因上面已经说了,因为会不断产生新对象,对性能不是很好,那么问题来了,为什么要使用StringBuffer/StringBuilder呢?它们效率就快些吗?带着各位看看jdk源代码来看看为什么它们效率更好.              

使用StringBuffer/StringBuilder来拼接字符串我们用的都是append方法,直接看看这个方法.

 (StringBuffer和StringBuilder的区别在于一个是线程安全的一个不是,StringBuffer线程安全的原因是因为它的方法上加上了synchronized关键字).

关于这个toStringCache它是一个类型为char数组的缓存变量,目前不用太在意它.重点是这个super.append(str)这行代码,直接调用父类的append方法,那就看看它爹,

Stringbuffer和Stringbuilder都继承于AbstractStringBuilder,直接来看看这个类的append方法

一行一行的解释吧,第一行和第二行:如果拼接的String是空就直接拼接一个null的字符串

ensureCapacityInternal方法

意思就是如果这个被拼接的字符串的长度比原本的字符串的长度还要长的话就执行value = Arrays.copyOf(value,newCapacity(minimumCapacity));那就继续看这个newCapacity方法

 private int newCapacity(int minCapacity) {
        // overflow-conscious code
		//定义个int 值为原本字符串的长度*2然后+2
        int newCapacity = (value.length << 1) + 2;
		//如果这个int变量减去要拼接的字符串长度要小于0,那么这个字符串的长度就等于要拼接字符串的长度
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
		//如果这个int变量小于或等于0  或者Integer的最大数值减去8(MAX_ARRAY_SIZE)减去这个int变量要小于0(也就是要比MAX_ARRAY_SIZE大的话)
		//那么就返回hugeCapacity方法(最大返回这个MAX_ARRAY_SIZE ),否则的话返回这个定义的Int变量
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }

Arrays.copyof我就不多说了,复制数组的方法,代表着将原来存放数据的char数组长度又加上后一个参数.

回到append方法

重点就是这个str.getChars(0, len, value, count);这个方法的意思就是:

将我自己(str)复制到value这个数组中(value就是实际存放字符的数组),后面的count是字符串的长度,拼接了嘛,肯定加上这个长度,然后返回自己

 

也就是说到这里这个字符串拼接的基本套路算是搞明白了,sb(StringBuffer/StringBuilder)都是通过它们的父类的拼接方法达到效果的,而这个拼接的过程将直白点就是复制数组的过程,毕竟字符串底层就是char数组,所以说效率至少要比直接产生新String对象效率好

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值