目录
StringBuffer与StringBuilder的共同之处:
StringBuffer与StringBuilder的不同之处:
StringBuilder/StringBuffer为什么是可变的呢?
前言:
思考:我们在实际的开发中,如果需要进行字符串的频繁拼接,会有什么问题?
因为java中的字符串是不可变的,每一次拼接都会产生新字符串。这样会占用大量的方法区内存。造成内存空间的浪费,给java的方法区字符串常量池带来很大的压力。
String s = "abc";
s += "hello";
就以上两行代码,就导致在方法区字符串常量池当中创建了3个对象。
所以如果以后需要进行大量字符串的拼接操作,建议使用JDK中自带的:
java.lang.StringBuffer
java.lang.StringBuilder
StringBuffer与StringBuilder的共同之处:
1、都继成了AbstractStringBuilder这个抽象类,实现了CharSequence接口
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
2、其append方法都是 super.append(str),调用了父类AbstractStringBuilder的append(String str)方法
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
3、初始容量都是16和扩容机制都是"旧容量*2+2"。
4、底层都是用char[]字符数组实现,且字符数组都是可变的,这点不同于String
StringBuffer与StringBuilder的不同之处:
1、StringBuffer中的方法都有synchronized关键字修饰。表示StringBuffer在多线程环境下运行是安全的。StringBuilder中的方法都没有synchronized关键字修饰,表示StringBuilder在多线程环境下运行是不安全的。
即:StringBuffer是线程安全的。StringBuilder是非线程安全的。
2、StringBuffer从JDK1.0就有了,StringBuilder是JDK5.0才出现
3、StringBuffer比StringBuilder多了一个toStringCache字段,用来在toString方法中进行缓存,每次append操作之前都先把toStringCache设置为null,若多次连续调用toString方法,可避免每次Arrays.copyOfRange(value, 0, count)操作,节省性能。
使用方法(以StringBuffer为例):
StringBuffer stringBuffer = new StringBuffer();
// 默认创建一个初始化容量为16个char[] 数组。(字符串缓冲区对象)
// 调用 append()方法对字符串进行拼接操作。
stringBuffer.append("a");
stringBuffer.append(3.14);
stringBuffer.append(true);
// append方法底层在进行追加的时候,如果byte数组满了,会自动扩容(复制进一个新的数组,删掉原来的数组)。
如何优化StringBuffer的性能?
在创建StringBuffer的时候尽可能给定一个初始化容量。最好减少底层数组的扩容次数。预估计一下,给一个大一些初始化容量。
如:
StringBuffer sb = new StringBuffer(100);
String为什么是不可变的?
String类中有一个byte[]数组,这个byte[]数组采用了final修饰,因为数组一旦创建长度不可变。并且被final修饰的引用一旦指向某个对象之后,不可再指向其它对象,所以String是不可变的!
StringBuilder/StringBuffer为什么是可变的呢?
StringBuffer/StringBuilder内部实际上也是一个byte[]数组,但这个byte[]数组没有被final修饰。StringBuffer/StringBuilder的初始化容量我记得应该是16,当存满之后会进行扩容,底层调用了数组拷贝的方法。所以StringBuilder/StringBuffer适合于使用字符串的频繁拼接操作。