天天看點

String StringBuilder和StringBuffer 結合源碼解析

String StringBuilder和StringBuffer 結合源碼解析

當我們在對字元串進行操作的時候,就會使用到String、StringBuilder和StringBuffer,然後在使用的時候我們還要注意三者的差別。

一、String

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,其引用沒有變化。      
String s = "abc";
char data[] = {'a', 'b', 'c'};
String str = new String(data);
System.out.println(str);//abc
System.out.println(str.length());//長度為3      
其實,String的内部是個數組,源碼如下:
/**
 * Allocates a new {@code String} so that it represents the sequence of
 * characters currently contained in the character array argument. The
 * contents of the character array are copied; subsequent modification of
 * the character array does not affect the newly created string.
 *
 * @param  value
 *         The initial value of the string
 */
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}      
那麼為什麼String類型的變量是不可變的呢?從源碼中解析:
/** The value is used for character storage. */
private final char value[];

/** Cache the hash code for the string */
private int hash; // Default to 0
      
這兩個屬性其中char是final的,也是不可變的,private類型,其中,在String中沒有兩個屬性的get、set方法,既無法去設定String的值,是以是無法改變的。

二、StringBuilder

源碼中:
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{}      
你會發現fianl的,既不可繼承的。      
/**
 * Constructs a string builder with no characters in it and an
 * initial capacity of 16 characters.
 */
public StringBuilder() {
    super(16);
}      
當你建立了一個StringBuilder的時候,其長度預設為16,如果長度大于了16,
/**
 * Constructs a string builder initialized to the contents of the
 * specified string. The initial capacity of the string builder is
 * <code>16</code> plus the length of the string argument.
 *
 * @param   str   the initial contents of the buffer.
 * @throws    NullPointerException if <code>str</code> is <code>null</code>
 */
public StringBuilder(String str) {
    super(str.length() + 16);
    append(str);
}
      
StringBuilder會在16的基礎上進行擴容。
/**
 * Constructs a string builder with no characters in it and an
 * initial capacity specified by the <code>capacity</code> argument.
 *
 * @param      capacity  the initial capacity.
 * @throws     NegativeArraySizeException  if the <code>capacity</code>
 *               argument is less than <code>0</code>.
 */
public StringBuilder(int capacity) {
    super(capacity);
}
      
你也可以自定義長度,但是長度不能小于0,否則會NegativeArraySizeException異常。
public StringBuilder append(boolean b) {
    super.append(b);
    return this;
}

public StringBuilder append(char c) {
    super.append(c);
    return this;
}

public StringBuilder append(int i) {
    super.append(i);
    return this;
}

public StringBuilder append(long lng) {
    super.append(lng);
    return this;
}

public StringBuilder append(float f) {
    super.append(f);
    return this;
}

public StringBuilder append(double d) {
    super.append(d);
    return this;
}
      
另外,你會發現StringBuilder不是線程安全的,所謂的線程安全就是在多線程的情況下,會出現多個多個append同時修改導緻的結果不一緻的不安全問題,是以如果要多線程使用StringBuilder的時候,要自己實作鎖的問題。建議在單線程下使用StringBuilder。      

三、StringBuffer

public final class StringBuffer
   extends AbstractStringBuilder
   implements java.io.Serializable, CharSequence{}      
StringBuffer與StringBuilder在實作功能上市類似的,其主要差別在于,StringBuffer是線程安全的, StringBuffer也是final的,不可繼承的。并且是可變的,使用synchronized使線程安全了。
public synchronized StringBuffer append(Object obj) {
    super.append(String.valueOf(obj));
    return this;
}

public synchronized StringBuffer append(String str) {
    super.append(str);
    return this;
}      
public synchronized StringBuffer append(boolean b) {
    super.append(b);
    return this;
}

public synchronized StringBuffer append(char c) {
    super.append(c);
    return this;
}

public synchronized StringBuffer append(int i) {
    super.append(i);
    return this;
}      

四、總結:

(1)String類型是被final修飾的,長度不可變的,即使使用concat方法,也是新建立了個對象,将值賦給了新的對象。      
(2)StringBuilder是長度可變的,可以使用append方法增加長度,預設長度為16,但是線程不安全,速度快。      
(2)StringBuffer是長度可變的,可以使用append方法增加長度,預設長度為16,是線程安全的,因為使用了所鎖的作用,與StringBuilder相比的速度比較慢。      
如有錯誤,請多多指教,謝謝,部落客會再接再厲,寫出更好的文章。