String、StringBuilder與StringBuffer
無論怎樣,學習Java,我的感受就是看源碼是怎麼實現的,這一點非常重要(這也要求了我們要有基本的英語閱讀能力)。
注意:在Java裏面一切對象都是引用,也就是new一個對象出來,它並不是對象本身,而是指向該對象的地址,類似於C++裏面的指針。
String
-
在Java中所有的字符串文字都是作爲String類的實例,如
System.out.println("abc"+2 instanceof String);
輸出結果爲true -
String對象是常量,在創建之後,賦予給對象的值不能改變,這一特性使他們可以被共享,而不用擔心在多線程裏導致變量不同步問題。
當我們看到如下代碼時會疑惑,str不是被重新賦值了嗎?
String str="abc";
str=str.substring(1);
System.out.println(str);
事實上,str並沒有被重新賦值,而只是使str重新指向了一個新的對象。以上代碼等價於:
char data[] = {'a', 'b', 'c'};
String str = new String(data);
str=str.substring(1);//
System.out.println(str);
而substring的源碼是這樣的
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
也就是說重新new了一個對象返回,使str指向新的String對象的地址
- Java爲字符串連接提供特殊運算符“+”,它是通過StringBuilder或StringBuffer的append方法實現的
StringBuffer
- 線程安全的、可變的字符序列。在StringBuffer中,在必要的方法裏都加了鎖synchronized,進行同步。儘管是線程安全的,但是在對多線程共享的原字符串進行操作期間,必須確保原字符串不被改變。即每次對字符串的操作是一個原子操作,必須對該臨界資源進行保護
- 當只在一個線程中使用StringBuffer時,可以用StringBuilder代替。在單線程中,實際上優先選用StringBuilder,因爲StringBuilder不需要同步,效率比StringBuffer快
StringBuilder
- StringBuilder出現於JDK1.5,不是線程安全的,所以只能在單線程中使用
StringBuilder和StringBuffer的共同點
- 通過append或insert方法將字符數組放入字符緩衝區,append方法總是追加到字符串末尾,而insert可以追加到指定位置
- 每個對象都有一定的緩衝區量,當沒有超出緩衝區量時,沒必要增加內部緩衝區空間大小,當超出時,會自動增加緩衝區大小,每次增加16
/*StringBuilder的構造函數*/
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
/*StringBuffer的構造函數*/
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}