首页 > 技术文章 > String StringBuilder和StringBuffer 结合源码解析

houstao 2018-01-10 12:32 原文

String StringBuilder和StringBuffer 结合源码解析

一、String 

  当我们在对字符串进行操作的时候,就会使用到String、StringBuilder和StringBuffer,然后在使用的时候我们还要注意三者的区别。

 public final class String implements java.io.Serializable, Comparable<String>, CharSequence {} 

在String的源码中,String的类是final的,因此该类是不能被继承的,那么为什么String类型的变量是不允许改变的呢,初学经常误认为是变化了的,其实不然,事实上是final在修饰基本类型的时候,是其变量的值不可变;修饰引用对象的时候,是其引用不可变,其对象的内容可变。
 String sb = "abc"; sb = "abcd"; 
sb变量会存入到jvm的栈内存中,只是sb刚开始的时候,是指向的abc,后面又指向了abcd,其引用没有变化。
 1 String s = "abc";
 2 char data[] = {'a', 'b', 'c'};
 3 String str = new String(data);
 4 System.out.println(str);//abc
 5 System.out.println(str.length());//长度为3其实,String的内部是个数组,
 6 //源码如下:
 7 /**
 8  * Allocates a new {@code String} so that it represents the sequence of
 9  * characters currently contained in the character array argument. The
10  * contents of the character array are copied; subsequent modification of
11  * the character array does not affect the newly created string.
12  *
13  * @param  value
14  *         The initial value of the string
15  */
16 public String(char value[]) {
17     this.value = Arrays.copyOf(value, value.length);
18 }
19 //那么为什么String类型的变量是不可变的呢?从源码中解析:
20 /** The value is used for character storage. */
21 private final char value[];
22 
23 /** Cache the hash code for the string */
24 private int hash; // Default to 0
25 //这两个属性其中char是final的,也是不可变的,private类型,其中,在String中没有两//个属性的get、set方法,既无法去设置String的值,因此是无法改变的。
 二、StringBuilder
 源码中:
 1 public final class StringBuilder
 2     extends AbstractStringBuilder
 3     implements java.io.Serializable, CharSequence{}//你会发现fianl的,既不可继承的。
 4 /**
 5  * Constructs a string builder with no characters in it and an
 6  * initial capacity of 16 characters.
 7  */
 8 public StringBuilder() {
 9     super(16);
10 }//当你创建了一个StringBuilder的时候,其长度默认为16。
11 /**
12  * Constructs a string builder initialized to the contents of the
13  * specified string. The initial capacity of the string builder is
14  * <code>16</code> plus the length of the string argument.
15  *
16  * @param   str   the initial contents of the buffer.
17  * @throws    NullPointerException if <code>str</code> is <code>null</code>
18  */
19 public StringBuilder(String str) {
20     super(str.length() + 16);
21     append(str);
22 }
23 //如果长度大于了16,StringBuilder会在16的基础上进行扩容。/**
24  * Constructs a string builder with no characters in it and an
25  * initial capacity specified by the <code>capacity</code> argument.
26  *
27  * @param      capacity  the initial capacity.
28  * @throws     NegativeArraySizeException  if the <code>capacity</code>
29  *               argument is less than <code>0</code>.
30  */
31 public StringBuilder(int capacity) {
32     super(capacity);
33 }
34 //你也可以自定义长度,但是长度不能小于0,否则会NegativeArraySizeException异常。    public StringBuilder append(boolean b) {
35     super.append(b);
36     return this;
37 }
38 
39 public StringBuilder append(char c) {
40     super.append(c);
41     return this;
42 }
43 
44 public StringBuilder append(int i) {
45     super.append(i);
46     return this;
47 }
48 
49 public StringBuilder append(long lng) {
50     super.append(lng);
51     return this;
52 }
53 
54 public StringBuilder append(float f) {
55     super.append(f);
56     return this;
57 }
58 
59 public StringBuilder append(double d) {
60     super.append(d);
61     return this;
62 }
另外,你会发现StringBuilder不是线程安全的,所谓的线程安全就是在多线程的情况下,会出现多个多个append同时修改导致的结果不一致的不安全问题,因此如果要多线程使用StringBuilder的时候,要自己实现锁的问题。建议在单线程下使用StringBuilder。
 三、StringBuffer
public final class StringBuffer
   extends AbstractStringBuilder
   implements java.io.Serializable, CharSequence{}
 StringBuffer与StringBuilder在实现功能上市类似的,其主要区别在于,StringBuffer是线程安全的,StringBuffer也是final的,不可继承的。并且是可变的,使用synchronized使线程安全了。
 1 public synchronized StringBuffer append(Object obj) {
 2     super.append(String.valueOf(obj));
 3     return this;
 4 }
 5 
 6 public synchronized StringBuffer append(String str) {
 7     super.append(str);
 8     return this;
 9 }public synchronized StringBuffer append(boolean b) {
10     super.append(b);
11     return this;
12 }
13 
14 public synchronized StringBuffer append(char c) {
15     super.append(c);
16     return this;
17 }
18 
19 public synchronized StringBuffer append(int i) {
20     super.append(i);
21     return this;
22 }

四、总结:
(1)String类型是被final修饰的,长度不可变的,即使使用concat方法,也是新创建了个对象,将值赋给了新的对象。
(2)StringBuilder是长度可变的,可以使用append方法增加长度,默认长度为16,但是线程不安全,速度快。
(3)StringBuffer是长度可变的,可以使用append方法增加长度,默认长度为16,是线程安全的,因为使用了所锁的作用,与StringBuilder相比的速度比较慢。
如有错误,请多多指教,谢谢,博主会再接再厉,写出更好的文章。


推荐阅读