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非线程安全的

猜你喜欢

转载自www.cnblogs.com/army-code/p/10600147.html