溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中String、StringBuffer和StringBuilder的區別是什么

發布時間:2022-02-24 10:43:33 來源:億速云 閱讀:174 作者:iii 欄目:開發技術

這篇文章主要講解了“Java中String、StringBuffer和StringBuilder的區別是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java中String、StringBuffer和StringBuilder的區別是什么”吧!

關于字符串的面試題除了內存分布、equals 比較,最常見的就是與StringBufferStringBuilder之間的區別了。

如果你回答:String 類是不可變的,StringBufferStringBuilder是可變類,StringBuffer是線程安全的,StringBuilder則不是線程安全的。

String字符串的拼接

關于String字符串前面多篇文章已經詳細描述過,它的不可變性也是因為每當通過“+”操作時,都會在內存中生成新的字符串而導致的。

String a = "hello ";
String b = "world!";
String ab = a + b;

其中 a 和 b 初始化時位于字符串常量池,ab 拼接后的對象位于堆中??梢院苤庇^的看出,經過拼接新生成了String對象。如果拼接多次,那么會生成多個中間對象。

上面的結論在Java8之前是成立的,在Java8時 JDK 對“+”號拼接進行了優化,上面所寫的拼接方式會被優化為基于StringBuilderappend方法進行處理。

stack=2, locals=4, args_size=1
     0: ldc           #2                  // String hello
     2: astore_1
     3: ldc           #3                  // String world!
     5: astore_2
     6: new           #4                  // class java/lang/StringBuilder
     9: dup
    10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
    13: aload_1
    14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    17: aload_2
    18: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    21: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    24: astore_3
    25: return

上面是通過 javap -verbose命令反編譯字節碼的結果,很顯然可以看到StringBuilder的創建和`append方法的調用。

此時,如果再籠統的回答:通過加號拼接字符串會創建多個String對象,因此性能比StringBuilder差,就是錯誤的了。因為本質上加號拼接的效果最終經過編譯器處理之后和StringBuilder是一致的。

如果你在代碼中使用如下寫法:

StringBuilder sb = new StringBuilder("hello ");
sb.append("world!");
System.out.println(sb.toString());

編譯器的插件甚至建議你使用String來代替。

StringBuffer與StringBuilder的對比

StringBufferStringBuilder實現的核心代碼基本一致,很多代碼都是公用的。這兩個類均繼承自抽象類AbstractStringBuilder。

我們來從構造方法到append方法來逐一看一下它們的區別。先看StringBuilder的構造方法:

public StringBuilder(String str) {
    super(str.length() + 16);
    append(str);
}

其中super方法便是調用的AbstractStringBuilder的構造方法。對應StringBuffer的構造方法中實現也是如此:

public StringBuffer(String str) {
    super(str.length() + 16);
    append(str);
}

從構造方法來說,StringBufferStringBuilder是一樣的。下面再看看append方法,StringBuilder實現如下:

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

StringBuffer對應的方法如下:

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

很顯然,在StringBufferappend方法實現上除了內部將toStringCache變量賦值為null,唯一的不同就是在方法上使用synchronized進行了同步處理。

toStringCache是用來緩存最后一次調用toString方法時生成的字符串,當StringBuffer內容變動時,該值也會變動。

通過上面的append方法的對比,我們可以很輕易的發現StringBuffer是線程安全的,StringBuilder是非線程安全的。當然,使用synchronized進行同步處理,性能便會降低很多。

StringBuffer與StringBuilder的底層實現

StringBufferStringBuilder都調用了父類的構造方法:

AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}

通過該構造方法我們可以看到它們用來處理字符串信息的關鍵屬性為value。在初始化時先初始化一個長度為傳入字符串長度+16的char[]數組,也就是value值,用來存儲實際的字符串。

在調用父類構造方法之后便是調用各自的append方法(見前面的代碼),而其中的核心處理又的調用父類的append方法:

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

上述代碼中其中str.getChars方法用來對傳入的str字符串進行拼接,在原有的value數組后面進行填充。而count用來記錄當前value數字中已經使用的長度。

那么,當沒有使用synchronized進行同步操作時,線程不安全發生在哪里?上面代碼中count+=len并不是原子操作。比如當前count為 5,兩個線程同時執行到 ++ 操作,拿到的值都為 5,執行完加操作之后賦值給count,兩個線程賦值都為 6,而不是 7。此時便出現了線程不安全的問題。

為什么String要設計成不可變

在 Java 中將String設計成不可變的是綜合考慮到各種因素的結果,有如下原因:

1、字符串常量池的需要,如果字符串可變,改變一個對象會影響到另外一個獨立的對象。不變這也是字符串常量池存在的前提條件。

2、Java 中String對象的哈希碼被頻繁地使用,比如在HashMap等容器中。字符串不變保證了hash碼的唯一性,可以方向緩存并使用。

3、安全性,確保String在當做參數傳遞時保持不變,避免安全隱患。比如在數據庫用戶名、密碼、訪問路徑等傳輸過程中的保持不變,防止改變字符串指向對象的值被改變。

4、由于字符串變量不可變,在多線程中可以被共享使用。

感謝各位的閱讀,以上就是“Java中String、StringBuffer和StringBuilder的區別是什么”的內容了,經過本文的學習后,相信大家對Java中String、StringBuffer和StringBuilder的區別是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女