Java中String、StringBuffer、StringBuilder的區別詳解

一 Java 中字符串的不變性

String 字符串常量,字符串長度不可變。
字符串的不變性:String 對象創建後則不能被修改,是不可變的
你肯定在想不對吧,字符串可以重新賦值修改。下面我們就來詳細說說。
重新賦值修改字符串其實是創建了新的對象,所指向的內存空間不同
我們來看個圖,更容易理解一點

String str1 ="Hello World"

聲明瞭一個字符串對象, str1 存放了到字符串對象的引用,在內存中的存放引用關係如下圖所示:

這裏寫圖片描述

對str1字符串進行賦值修改

str1 ="Hello World Java"

其實質是創建了新的字符串對象,變量 str1 指向了新創建的字符串對象,如下圖所示:

這裏寫圖片描述

下面看看 String 不變性的原因

/** The value is used for character storage. */
private final char value[];

/** The offset is the first index of the storage that is used. *
private final int offset;

/** The count is the number of characters in the String. */
private final int count;

用於存放字符的數組被聲明爲final的,因此只能賦值一次,不可再更改。所以可以知道String對象是不可變的。

一旦一個字符串在內存中創建,則這個字符串將不可改變。如果需要一個可以改變的字符串,我們可以使用StringBuffer或者StringBuilder。

二 StringBuffer和StringBuilder介紹

StringBuilder:字符串變量(非線程安全)。在內部,StringBuilder對象被當作是一個包含字符序列的變長數組。

StringBuffer:字符串變量(Synchronized,即線程安全)。如果要頻繁對字符串內容進行修改,出於效率考慮最好使用StringBuffer,如果想轉成String類型,可以調用StringBuffer的toString()方法。

AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,是一個抽象類定義了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。

三 String,StringBuffer和StringBuilder區別

3.1 從可變與不可變比較

String類中用於存放字符的數組被聲明爲final的,因此只能賦值一次,不可再更改。所以可以知道String對象是不可變的。

StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中用於存放字符的數組沒有被聲明爲final的。所以可以知道StringBuilder與StringBuffer對象是可變的。

3.2 是否多線程安全

String中的對象是不可變的,也就可以理解爲常量,顯然線程安全。

StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,所以是線程安全的。看下源碼:

    public synchronized StringBuffer append(String str) {
        super.append(str);
        return this;
    }

StringBuilder並沒有對方法進行加同步鎖,所以是非線程安全的。看下源碼:

    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

四 使用策略

  1. 基本原則:如果要操作少量的數據,用String ;單線程操作大量數據,用StringBuilder ;多線程操作大量數據,用StringBuffer。
  2. 不要使用String類的”+”來進行頻繁的拼接,因爲那樣的性能極差的,應該使用StringBuffer或StringBuilder類,這在Java的優化上是一條比較重要的原則。
  3. StringBuilder一般使用在方法內部來完成類似”+”功能,因爲是線程不安全的,所以用完以後可以丟棄。StringBuffer主要用在全局變量中。
  4. 爲了獲得更好的性能,在構造 StringBuffer 或 StringBuilder 時應儘可能指定它們的容量。當不指定容量(capacity)時默認構造一個容量爲16的對象。
  5. 如果程序不是多線程的,那麼使用StringBuilder效率高於StringBuffer。
發佈了47 篇原創文章 · 獲贊 41 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章