JDK源码学习--String篇(四) 终结篇
StringBuilder和StringBuffer
前面讲到String是不可变的,如果需要可变的字符串将如何使用和操作呢?JAVA提供了连个操作可变字符串的类,StringBuilder和StringBuffer,从源码中可以看到这两个类都是采用final修饰,并且继承抽象类AbstractStringBuilder的。
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
}
同String相同,都是采用字符数组来存储的,但是String中使用final修饰,是不可变的。
StringBuffer和StringBuilder都提供了一些常用的操作字符串的方法,有什么不同之处呢?还是从源码着手分析:
StringBuffer源码解析
/**
* Constructs a string buffer with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuffer() {
super(16);
}
看AbstractStringBuilder可知:
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
无参构造函数,构造一个初始容量为16的字符串缓冲区。同时提供多个有参的构造函数,其中:
/**
* Constructs a string buffer initialized to the contents of the
* specified string. The initial capacity of the string buffer is
* {@code 16} plus the length of the string argument.
*
* @param str the initial contents of the buffer.
*/
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
这个构造函数需提供一个字符串参数,构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容,该字符串的初始容量为 16 加上字符串参数的长度。其中的append方法是重要部分。
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
// AbstractStringBuilder
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;
}
append方法前加了同步锁,保证了线程安全,StringBuffer中很多方法都采用同步锁,保证了多线程操作时的同步安全。
其中的ensureCapacityInternal方法中对存储空间的分配:当存储空间不够用的时候,重新new char[],存储空间为:(原始大小+1)*2,最大为:Integer.MAX_VALUE ,
StringBuilder
StringBuilder通StringBuffer操作逻辑基本一致,只是没有做同步处理。
总结
String:字符常量
StringBuffer:字符变量【线程安全】
StringBuilder:字符变量【非线程安全】
由此也可知,在大部分情况下,三者在执行速度方面的比较:StringBuilder > StringBuffer > String
用法总结:
String:用于少量需要对字符串进行操作【因为String 每次生成对象都会对系统性能产生影响,当内存中无引用对象产生过多时,GC就会开始工作】
StringBuilder:单线程下,多次大量操作字符串【字符串处理时不会产生新的对象,而是对象自身做改变】
StringBuffer:多线程下,多次大量操作字符串【字符串处理时不会产生新的对象,而是对象自身做改变】