关于String,StringBuffer,和StringBuilder的一点心得

本文详细探讨了Java中String的内部实现机制,包括其不可变性和字符串池的工作原理。同时,对比分析了StringBuilder与StringBuffer的区别,以及它们在字符串拼接过程中的内存分配和扩容策略。

一、关于String,首先需要知道String是final的,内部实现是一个final的char[],它有两种构造方法,一种是通过new String 在JVM的堆内存进行分配。一种是通过String a = "abc"这种方式,这种JVM首先会在String pool中查找是否有“abc”,如果有则把地址给a,若没有,则创建一个,并放入到String pool中。
上面也就解释了
String a = "abc";
String b = "abc";
String c = new String("abc");
a==b为true,a==c为false.
但是有一种特殊的
String d = a+"d";//此时d的内容为abcd
String e = "abcd";
String f = "ab"+"cd";
d==e为false, e==f 为true
可以认为是这个样子的,所有用“”修饰的,都在String pool中,所以e和f相等
那么来看d和e,d通过a+“d”实际上执行了new StringBuilder().append(a).append("d").toString();它是在JVM的堆内存生成了一个对象,所以和String pool的地址不可能一样。
另外看源码,发现String中有很多final并没有给初始值,这样做是可以的,只要在构造方法中给初始值就行了。也算是突破了我的一个认知。
二。StringBuilder非线程安全,StringBuffer是线程安全的。(StringBuffer方法通过synchronized加了同步锁)
这里说两点:
第一:关于append的实现,appen是通过传入的字符串的getChars实现的。
例如:(StringBuilder也一样,都是继承了AbstractStringBuilder,appen就是在该类中实现的。)
StringBuffer d = new StringBuffer();
d.append("a");
此处appen是通过传入的字符串"a"的getChars(int start,int end,char c[],int offset)方法实现的,该方法的作用是将当前字符串从start到end-1位置上的字符复制到字符数组c中,并从c的offset处开始存放。
第二:关于扩容
每次append时都需要对当前数组进行判断,如果长度超过当前数组的长度,则对数组进行扩容。即当前数组长度的2倍再加上2(这里加2,我自己认为是为了防止初始化的时候用户传了0,即当前数组长度为0,乘以2还是0这种情况,当然默认值时16),
下面是代码:
(当然扩容时不能说就是2倍+2,如果2倍+2还是比需求的量要小的话,那就是当前的需求量。minimumCapacity即为当前的需求量。)

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






StringStringBufferStringBuilder都是Java中用于处理字符串的类。 String是一个不可变的字符串类,也就是说一旦创建了一个String对象,它的值就不能被修改。每次对String进行修改操作时,都会创建一个新的String对象,这样会浪费内存空间时间。因此,当需要频繁地对字符串进行修改时,使用String并不高效。 StringBufferStringBuilder是可变的字符串类,它们可以被用来进行字符串的修改操作。StringBufferStringBuilder的主要区别在于StringBuffer是线程安全的,而StringBuilder是非线程安全的。这意味着在多线程环境下,如果有多个线程同时访问一个StringBuffer对象,它们是安全的;而多个线程同时访问一个StringBuilder对象时,可能会导致数据错乱。 使用StringBufferStringBuilder的场景通常是在需要频繁地对字符串进行修改的情况下。例如,在循环中拼接字符串、在递归函数中修改字符串等情况下,使用StringBufferStringBuilder可以提高性能。 如果需要将StringBufferStringBuilder转换为String对象,可以使用两种方式。一种是调用它们的toString()方法,将其转换为String对象。另一种是使用String的构造器String(StringBuffer buffer)来创建一个新的String对象,将StringBufferStringBuilder的内容复制到新的String对象中。 总结起来,String是不可变的字符串类,而StringBufferStringBuilder是可变的字符串类,适用于需要频繁修改字符串的场景。转换为String对象可以通过调用toString()方法或使用String的构造器来实现。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值