String,StringBuffer,StringBuilder源码分析
1.类结构
String Diagrams
StringBuffer Diagrams
StringBuilder Diagrams
通过以上Diagrams可以看出,String,StringBuffer,StringBuilder都是CharSequence的实现类,其中StringBuffer,StringBuilder都是AbstractStringBuilder的子类
2.源码分析
a>String
通过String的API可以看出String类中没有像StringBuffer和StringBuilder类对字符串进行append/insert/delete操作,当然我们可以通过str1+str2的方式对String对象进行改变,但是这种方式的改变,不但String对象值改变了,而且对象也改变了.我们可以通过下面代码进行验证
1 public static void main(String[] args) throws Exception{
2 String str = new String("string");
3 System.out.println(str.hashCode()); //输出:-891985903
4 str += "123";
5 System.out.println(str.hashCode()); //输出:-189327231
6 }
通过StringBuffer,StringBuilder源码分析可以推测(代码第4行)实现过程:
String源码关键变量:
str += "123"代码实现:
1 public static void main(String[] args) throws Exception{
2 Charset charset = Charset.forName("utf-8");
3 /**
4 * String str = new String("string");
5 * 相当于初始化String对象过程中private final char value[];
6 * 即valuestring=value
7 */
8 char[] valuestring = charset.decode(charset.encode("string")).array();
9 /**
10 * 初始化String对象 "123"
11 * 相当于初始化String对象过程中private final char value[];
12 * 即valuestring=value
13 */
14 char[] value1123 = charset.decode(charset.encode("123")).array();
15
16 /**
17 * str += "123" 结果对象的 private final char value[];
18 */
19 char[] valuecopy = new char[9];
20
21 /**
22 * 相当于字符串拼接过程
23 * 即新建一个char数组valuecopy,用来存储valuestring,value1123
24 */
25 System.arraycopy(valuestring,0,valuecopy,0,valuestring.length);
26 System.arraycopy(value1123,0,valuecopy,valuestring.length,value1123.length);
27
28 System.out.println(new String(valuecopy));//输出:string123
29
30 }
通过查看源码我们发现System.arraycopy是本地方法,即调用的C语言实现的方法
1 public static native void arraycopy(Object src, int srcPos,
2 Object dest, int destPos,
3 int length);
不过我们通过jdk-api知道是数组的拷贝,我们可以想象下,每次扩展String对象值,都需要新建数组并copy原来的数据,效率肯定会很低,因此我们在对字符串改变次数少的时候可以考虑使用String
b>StringBuffer
关键变量:
1 /**
2 * A cache of the last value returned by toString. Cleared
3 * whenever the StringBuffer is modified.
4 */
5 private transient char[] toStringCache;
6
7 /**
8 * The value is used for character storage.
9 */
10 char[] value;//StringBuffer是把字符串放到value容器中
11
12 /**
13 * The count is the number of characters used.
14 */
15 int count;//已使用的空间
StringBuffer是通过ensureCapacityInternal(int minimumCapacity)方法防止数据溢出的,当append字符串str时,先判断count+str.length-value.length>0如果value空间不足时,新建空间newValue并把value赋值到newValue,最后把newValue赋值给value,源码为:
1 public AbstractStringBuilder append(String str) {
2 if (str == null)
3 return appendNull();
4 int len = str.length();
5 ensureCapacityInternal(count + len);
6 str.getChars(0, len, value, count);//把字符串放到value空间中
7 count += len;
8 return this;
9 }
10 //确定value空间是否足够,不足则新建空间,并复制数据
11 private void ensureCapacityInternal(int minimumCapacity) {
12 // overflow-conscious code
13 if (minimumCapacity - value.length > 0) {
14 value = Arrays.copyOf(value,
15 newCapacity(minimumCapacity));
16 }
17 }
其中insert,delete原理大致相同,都是对value空间的操作
需要注意的是:
1>StringBuffer所有public修饰的方法都是通过synchronized关键字保证线程安全的
2>StringBuffer有个toStringCache变量,用来缓存数据的,每当对value操作之前都需要把toStringCache数据清除
变量解释:返回最后一次toString的缓存值,一旦StringBuffer被修改就清除这个缓存值。
c>StringBuilder
StringBuilder的实现原理和StringBuffer的实现原理是相同的,只是StringBuilder是非线程安全的,并且没有使用toStringCache
总结:
执行速度:String<StringBuffer<StringBuilder
安全性:StringBuffer是线程安全的,StringBuilder非线程安全的