JDK 1.8 源碼解析 String、StringBuilder和StringBuffer的異同
JDK提供了String、StringBuilder和StringBuffer這三個類來處理字符串,其中StringBuilder類是在JDK 1.5中新增的。
不同點如下:
1 是否有父類
String沒有父類。
// String類不能被繼承
// 實現了Serializable、Comparable和CharSequence(字符序列)接口
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
StringBuilder和StringBuffer都繼承了抽象類AbstractStringBuilder。
// 抽象類AbstractStringBuilder
// 實現了Appendable(可追加)和CharSequence(字符序列)接口
abstract class AbstractStringBuilder implements Appendable, CharSequence
1 // StringBuilder類不能被繼承
2 // 繼承了抽象類AbstractStringBuilder
3 // 實現了Serializable和CharSequence接口
4 public final class StringBuilder
5 extends AbstractStringBuilder
6 implements java.io.Serializable, CharSequence
1 // StringBuffer類不能被繼承
2 // 繼承了抽象類AbstractStringBuilder
3 // 實現了Serializable和CharSequence接口
4 public final class StringBuffer
5 extends AbstractStringBuilder
6 implements java.io.Serializable, CharSequence
2 可變性
屬性字符數組不可變(數組引用不可變,數組元素可變),String不可變,對於每個不同的字符串都需要一個單獨的String對象。
// 字符數組
private final char value[];
AbstractStringBuilder中的字符數組可變,StringBuilder和StringBuffer可變。StringBuilder和StringBuffer都有insert()插入方法、delete()刪除方法和append()末尾追加方法,調用System.arraycopy()方法來實現數組元素的拷貝。
// 字符數組
char[] value;
3 是否線程安全
String對象不可變,本質上是線程安全的。StringBuilder和StringBuffer的方法實現大致相同,不同之一是StringBuffer類的方法上加了synchronized關鍵字,即加了對象鎖,該鎖會鎖住整個對象,效率低。也就是說,StringBuffer是線程安全的。
// 獲取子串順序下從某位置開始首次出現的位置
@Override
public int indexOf(String str, int fromIndex) {
return super.indexOf(str, fromIndex);
}
@Override
public synchronized int indexOf(String str, int fromIndex) {
return super.indexOf(str, fromIndex);
}
相同點如下:
1 substring()方法(截取字符串,即獲取子串)
String中的substring()方法:
1 // 截取字符串
2 public String substring(int beginIndex, int endIndex) {
3 if (beginIndex < 0) { // 如果起始下標<0
4 throw new StringIndexOutOfBoundsException(beginIndex);
5 }
6 if (endIndex > value.length) { // 如果末尾下標>字符數組長度
7 throw new StringIndexOutOfBoundsException(endIndex);
8 }
9 int subLen = endIndex - beginIndex; // 獲取截取長度
10 if (subLen < 0) { // 如果截取長度<0
11 throw new StringIndexOutOfBoundsException(subLen);
12 }
13 return ((beginIndex == 0) && (endIndex == value.length)) ? this
14 : new String(value, beginIndex, subLen);
15 }
AbstractStringBuilder中的substring()方法:
1 // 獲取子串,返回String對象的引用
2 public String substring(int start, int end) {
3 if (start < 0) // 如果開始位置<0
4 throw new StringIndexOutOfBoundsException(start);
5 if (end > count) // 如果結束位置>count
6 throw new StringIndexOutOfBoundsException(end);
7 if (start > end) // 如果開始位置>結束位置
8 throw new StringIndexOutOfBoundsException(end - start);
9 // 返回String對象的引用
10 return new String(value, start, end - start);
11 }
substring()方法都是創建新的String對象並返回該對象引用。
總結
String適用於常量,StringBuilder適用於非並發情況下的字符串操作,StringBuffer適用於並發情況下的字符串操作。
參考資料
從Java源碼角度徹底理解String,StringBuilder和StringBuffer的區別
《Effective Java 中文版 第2版》 P66-67
JDK 1.8 源碼解析 String、StringBuilder和StringBuffer的異同