1. 程式人生 > >JDK 1.8 源碼解析 String、StringBuilder和StringBuffer的異同

JDK 1.8 源碼解析 String、StringBuilder和StringBuffer的異同

sta his 獲取 對象鎖 創建 實現 buffer enc 字符串

  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的異同