String、StringBuffer、StringBuidler 知识整理
String、StringBuffer、StringBuidler、这三个家伙,大家都不陌生,肯定也都会用。三者异同大家都能说出来,但是其根本原因是什么呢?带着下面问题,学习一下。
第一、String与后两者不同,为什么String对象不可变,后两者对象可变呢?
第二、线程安全方面,为什么StringBuffer比StringBuidler安全呢?
1.我们首先看String的源码(截取一小部分):
1 public final class String 2 implements java.io.Serializable, Comparable<String>, CharSequence { 3 /** The value is used for character storage. */
我标红的地方就是关键,String中的字符串是通过数组char来存储的,而它的修饰符是final,这就解释了为什么String对象不可变的原因。 4 private final char value[]; 5 6 /** Cache the hash code for the string */ 7 private int hash; // Default to 0
2.看看StringBuilder源码
它继承了AbstractStringBuilder这个类。
1 @Override 2 public StringBuilder append(CharSequence s) { 3 super.append(s); 4 return this; 5 }
在append()方法里,会调用父类AbstractStringBuilder的append()的方法。
父类append方法如下 代码2
1 // Documentation in subclasses because of synchro difference 2 @Override 3 public AbstractStringBuilder append(CharSequence s) { 4 if (s == null) 5 return appendNull(); 6 if (s instanceof String) 7 return this.append((String)s); 8 if (s instanceof AbstractStringBuilder) 9 return this.append((AbstractStringBuilder)s); 10 11 return this.append(s, 0, s.length()); 12 }
1 @Override 代码3(标识用) 2 public AbstractStringBuilder append(CharSequence s, int start, int end) { 3 if (s == null) 4 s = "null"; 5 if ((start < 0) || (start > end) || (end > s.length())) 6 throw new IndexOutOfBoundsException( 7 "start " + start + ", end " + end + ", s.length() " 8 + s.length()); 9 int len = end - start; 10 ensureCapacityInternal(count + len); 11 for (int i = start, j = count; i < end; i++, j++) 12 value[j] = s.charAt(i); 13 count += len; 14 return this; 15 }
上述代码3中的12行value在源码中定义是 char[] value; 没有final关键字。
3.说说StringBuffer
它也是继承了AbstractStringBuilder这个类,
1 @Override 2 public synchronized StringBuffer append(CharSequence s) { 3 toStringCache = null; 4 super.append(s); 5 return this; 6 }
在append方法中,加入了synchronized关键字,所以在多想城称重,StringBuffer是安全的,但是安全的代价就是影响了一些速度,因此速度肯定慢于StringBuilder。这里也就解释文章开头提出的第二个问题。
简单的整理记录一下。不对的地方欢迎指正。
努力到无能为力,奋斗到感动上天!