首頁 > 軟體

Java中String和StringBuffer及StringBuilder 有什麼區別

2022-06-15 10:00:14

前言:

String 是 Java 語言非常基礎和重要的類,提供了構造和管理字串的各種基本邏輯。它是典型的 Immutable 類,被宣告成為 final class,所有屬性也都是 final 的。也由於它的不可變性,類似拼接、裁剪字串等動作,都會產生新的 String 物件。由於字串操作的普遍性,所以相關操作的效率往往對應用效能有明顯影響。 StringBuffer 是為解決上面提到拼接產生太多中間物件的問題而提供的一個類,我們可以用 append 或者 add 方法,把字串新增到已有序列的末尾或者指定位置。StringBuffer 本質是一個執行緒安全的可修改字元序列,它保證了執行緒安全,也隨之帶來了額外的效能開銷,所以除非有執行緒安全的需要,不然還是推薦使用它的後繼者,也就是 StringBuilder。 StringBuilder 是 Java 1.5 中新增的,在能力上和 StringBuffer 沒有本質區別,但是它去掉了執行緒安全的部分,有效減小了開銷,是絕大部分情況下進行字串拼接的首選。

String類為什麼是immutable(不可變的)

不可變類指的是物件一旦建立成功,就無法改變物件的值。JDK中很多類設計為不可變的Integer,Long和String等。相對應的改法中大多是可變類,建立成功後可以動態修改成員變數的屬性值;

如何保證不可變

  • 類新增final修飾符,保證類是不可以被繼承的;類繼承會破壞類的不可變機制,只要覆蓋父類別的成員方法,並且在裡面修改成員變數的值,那麼所有子類以父類別的形式出現的地方,類的屬性都會被修改掉
  • 類成員屬性設定為private,final的;這樣可以保證成員屬性是不可變的,但是僅僅這樣還不夠,因為如果成員變數是參照物件的話,可以改變參照物件的成員變數;通過第四點可以避免這一點;
  • 不提供修改成員變數的方法,比如setter;
  • 通過構造器構造物件,並進行深拷貝;如果是直接通過參照傳入的物件直接賦值給成員,還是可以通過修改外部參照變數導致改變內部變數的值;

String的原始碼如下:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;
    /**
     * Class String is special cased within the Serialization Stream Protocol.
     *
     * A String instance is written into an ObjectOutputStream according to
     * <a href="{@docRoot}/../platform/serialization/spec/output.html" rel="external nofollow" >
     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
     */
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];
    /**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     */
    public String() {
        this.value = "".value;
    }
    /**
     * Initializes a newly created {@code String} object so that it represents
     * the same sequence of characters as the argument; in other words, the
     * newly created string is a copy of the argument string. Unless an
     * explicit copy of {@code original} is needed, use of this constructor is
     * unnecessary since Strings are immutable.
     *
     * @param  original
     *         A {@code String}
     */
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

    /**
     * Allocates a new {@code String} so that it represents the sequence of
     * characters currently contained in the character array argument. The
     * contents of the character array are copied; subsequent modification of
     * the character array does not affect the newly created string.
     *
     * @param  value
     *         The initial value of the string
     */
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

通過原始碼可以看出來String是如何保證不可變的:

  • String類是finaly的,不允許繼承
  • 成員變數value是private,final的
  • value沒有setter方法
  • 構造方法,是通過克隆的方式來構造的
  • 返回value時,通過克隆的方式返回

string類為不可變物件的好處

字串常數池的需要:

String aaa= "someString"; String bbb = "someString"; 這兩個物件指向同一個記憶體,字串常數池的好處是,在大量使用字串的時候,可以節省記憶體,提供效率;如果String是可變物件,那麼修改了一個,其他參照的地方全部發生變化了。

執行緒安全的考慮:

在並行場景下,多個執行緒同時讀一個資源,不會引發競爭,但是同時寫操作會引發競爭,string的不可變特點,所以執行緒安全的。

支援hash快取:

因為字串是不可變的,所以建立的時候hash被快取下來了,不需要重新計算,使得字串很適合做Map的鍵,處理速度要快過其他的物件。

到此這篇關於Java中String和StringBuffer及StringBuilder 有什麼區別的文章就介紹到這了,更多相關Java String 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com