Java基礎——String/StringBuilder/StringBuffer的區別
1. String
public final class String implements java.io.Serializable, Comparable<String>, Charsequence {
...
private final char[] value;
...
}
String x = "ab";
x += "cd";
a. JDK 1.8之前,需要三塊內存完成操作,一是原來的"ab"字符串內存,一是新拼接來的"cd"字符串內存,一是拷貝兩個字符串拼接在一起的新的String對象的字符串的內存;
b. JDK 1.8之後,編譯器會將"+"字符串拼接操作根據需要編譯成StringBuilder或者StringBuffer來處理。
String內部是一個final char[]存儲的,被初始化後就不能改變這個數組,對String重新賦值實質上是在heap中重新創建String對象
2. StringBuilder
public final class StringBuilder extends AbstractStringBuilder
implements java.io.Serializable, Charsequence {
}
StringBuilder的數據是存儲在一個char[]中,再不斷調用append或者delete方法來增加或刪除字符串
StringBuilder的append方法最終調用的是父類AbstractStringBuilder的append方法
詳細添加步驟見下面註釋
abstract class AbstractStringBuilder implements Appendable, CharSequence {
char[] value;
...
public AbstractStringBuilder append(String str) {
if (str == null) // append空字串處理
return appendNull();
// 計算要添加的字串長度
int len = str.length();
// 確保char數組的容量足夠,對數組擴容,
// 實質是調用Array.copyOf把原來的字串拷貝到新的長度的char[]中
ensureCapacityInternal(count + len);
// 將需要append的字符串拷貝到新的value[]的末端
str.getChars(0, len, value, count);
// 更新char[]長度
count += len;
return this;
}
}
3. StringBuffer
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
// 在toString()時做了優化,如果這個臨時的數組不爲空就直接使用此數組,
// 一旦修改(增刪字符)操作,都會被置空,並等下一次toString爲它賦值,
// 在未修改的情況下再次toString將提高效率
private transient char[] toStringCache;
...
}
- 附:關於transient修飾符(字面意思爲臨時的)
1. 被此修飾符修飾後,變量將不是對象持久化的一部分,被序列化後無法訪問(即transient變量不能被序列化);
2. 只能修飾類的成員變量和靜態變量,不能修飾局部變量、方法、類,存在這種修飾的變量的類必須實現Serializable接口;
3. transient變量不能被反序列化(很好理解,本身不能被序列化,序列化後再反序列化自然不能得到之前的值了)
所以這個臨時的變量就是在序列化前可用,序列化後,序列化再反序列化都不可用了。
StringBuffer與StringBuilder的區別是:
- StringBuffer在創建時,自帶了長度16,有初始字符串也會在字串長度基礎上加16
- StringBuffer是線程安全的,方法都是同步方法,適用於多線程共享的變量,在性能上爲了保證同步會有所犧牲。