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相比的速度比較慢。
如有錯誤,請多多指教,謝謝,部落客會再接再厲,寫出更好的文章。