JavaRush /Java Blog /Random-TW /Java中String、StringBuffer和StringBuilder簡介

Java中String、StringBuffer和StringBuilder簡介

在 Random-TW 群組發布
Java 中有三個類別用於處理文字資料:StringStringBufferStringBuilder。每個開發人員在學習語言之初都會遇到第一個問題。剩下的兩個呢?它們有什麼區別,什麼時候使用一個或另一個類別更好?一般來說,它們之間的差異很小,但最好在實踐中理解一切:) Java 中的 String、StringBuffer 與 StringBuilder 簡介 - 1

字串類

這個類別代表一個字元序列。程式中定義的所有字串文字(例如“This is String”)都是 String 類別的實例。 字串有兩個基本特徵:
  • 這是一個不可變的類
  • 這是最後一堂課
一般來說,String 類別不能有子類別 ( final),且該類別的實例在建立後不能修改 ( immutable)。這給了 String 類別幾個重要的優點:
  1. 由於不變性,String 類別實例的雜湊碼被快取。不需要每次都評估,因為物件的欄位值在創建後就永遠不會改變。當使用此類作為 的鍵時,這會提供高效能HashMap

  2. String 類別可以在多執行緒環境中使用,無需額外的同步。

  3. String類別的另一個特點是它重載了+Java中的「」運算子。因此,字串的連接(相加)非常簡單:

public static void main(String[] args) {
    String command = "Follow" + " " + "the" + " " + "white" + " " + "rabbit";
    System.out.println(command); // Follow the white rabbit
}
在幕後,字串連接是由 StringBuilder 或 StringBuffer 類別(由編譯器決定)和一個方法append(我們稍後將討論這些類別)執行的。如果我們將 String 類別的實例與其他類別的實例相加,後者將被簡化為字串表示形式:
public static void main(String[] args) {
    Boolean b = Boolean.TRUE;
    String result = "b is " + b;
    System.out.println(result); //b is true
}
這是 String 類別的另一個有趣的屬性:任何類別的物件都可以使用toString()類別中定義的方法轉換為字串表示形式Object,並由所有其他類別繼承。通常,物件上的 toString() 方法會被隱含呼叫。例如,當我們在螢幕上顯示某些內容或將 String 新增到另一個類別的物件時。String 類別還有一項功能。Java 程式碼中定義的所有字串文字(例如「asdf」)都會在編譯時快取並添加到所謂的字串池中。如果我們運行以下程式碼:
String a = "Wake up, Neo";
String b = "Wake up, Neo";

System.out.println(a == b);
我們將在控制台中看到true,因為變數a實際上b引用在編譯時添加到字串池中的 String 類別的相同實例。即不會創建具有相同值的類別的不同實例,並且節省了記憶體。

缺陷:

不難猜測 String 類別主要用於處理字串。但在某些情況下,String類別的上述特性可能會從優點變成缺點。一旦在 Java 程式碼中建立了字串,通常會對它們執行許多操作:
  • 將字串轉換為不同的暫存器;
  • 子串提取;
  • 級聯;
  • ETC。
我們來看看這段程式碼:
public static void main(String[] args) {

    String s = " Wake up, Neo! ";
    s = s.toUpperCase();
    s = s.trim();

    System.out.println("\"" + s + "\"");
}
乍一看,我們似乎只是翻譯了“醒來,尼奧!”這句話。改為大寫,從此字串中刪除多餘的空格並將其用引號引起來。事實上,由於String類別的不可變性,每次操作都會建立新的字串實例並丟棄舊的字串實例,從而產生大量垃圾。如何避免記憶體浪費?

字串緩衝區類

要處理由於修改 String 物件而產生的臨時垃圾,可以使用 StringBuffer 類別。這是mutable一個類,即 多變。StringBuffer 類別的物件可以包含一組特定的字符,可以透過呼叫某些方法來更改其長度和值。讓我們看看這個類別是如何運作的。若要建立新對象,請使用其建構函數之一,例如:
  • StringBuffer() - 將建立一個空(無字元)對象
  • StringBuffer(String str) - 將基於 str 變數建立一個物件(包含同一序列中 str 的所有字元)
實踐:
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = new StringBuffer("Not empty");
Java 中透過 StringBuffer 進行字串連線是使用append. 一般來說,StringBuffer 類別中的方法append被重載為幾乎可以接受任何資料類型:
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer();

    sb.append(new Integer(2));
    sb.append("; ");
    sb.append(false);
    sb.append("; ");
    sb.append(Arrays.asList(1,2,3));
    sb.append("; ");

    System.out.println(sb); // 2; false; [1, 2, 3];
}
該方法append傳回呼叫它的物件(像許多其他方法一樣),這允許在「鏈」中呼叫它。上面的例子可以這樣寫:
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer();

    sb.append(new Integer(2))
            .append("; ")
            .append(false)
            .append("; ")
            .append(Arrays.asList(1,2,3))
            .append("; ");

    System.out.println(sb); // 2; false; [1, 2, 3];
}
StringBuffer 類別有許多處理字串的方法。讓我們列出主要的:
  • delete(int start, int end)start— 刪除從位置 開始、結束的字元子字串end
  • deleteCharAt(int index)— 刪除位置處的字符index
  • insert(int offset, String str)str—在位置插入一行offset。該方法insert也是重載的並且可以採用不同的參數
  • replace(int start, int end, String str)- 將替換從一個位置startend另一個位置的所有字符str
  • reverse()— 反轉所有字元的順序
  • substring(int start)- 將傳回從位置開始的子字串 start
  • substring(int start, int end)start- 將返回從一個位置開始到另一個位置的子字串end
官方文件中有完整的方法和建構函式清單。上述方法如何發揮作用?讓我們在實踐中看看:
public static void main(String[] args) {
     String numbers = "0123456789";

     StringBuffer sb = new StringBuffer(numbers);

     System.out.println(sb.substring(3)); // 3456789
     System.out.println(sb.substring(4, 8)); // 4567
     System.out.println(sb.replace(3, 5, "ABCDE")); // 012ABCDE56789

     sb = new StringBuffer(numbers);
     System.out.println(sb.reverse()); // 9876543210
     sb.reverse(); // Return the original order

     sb = new StringBuffer(numbers);
     System.out.println(sb.delete(5, 9)); // 012349
     System.out.println(sb.deleteCharAt(1)); // 02349
     System.out.println(sb.insert(1, "One")); // 0One2349
    }

優點:

  1. 如同已經提到的,StringBuffer 是一個可變類,因此使用它不會產生與 String 相同數量的記憶體垃圾。因此,如果對字串進行大量修改,最好使用StringBuffer.

  2. StringBuffer是一個線程安全的類別。它的方法是同步的,實例可以被多個執行緒同時使用。

缺陷:

一方面,線程安全是類別的優點,另一方面,它又是缺點。同步方法比非同步方法慢。這就是 StringBuilder 發揮作用的地方。讓我們弄清楚這是一個什麼樣的Java類別——StringBuilder,它有哪些方法以及它的特點是什麼。

字串生成器類

Java中的StringBuilder是一個表示字元序列的類別。除了線程安全性之外,它在各方面都與 StringBuffer 非常相似。StringBuilder 提供了類似 StringBuffer 的 API。讓我們使用一個已經熟悉的範例來示範這一點,將變數宣告從 StringBufer 替換為 StringBuilder:
public static void main(String[] args) {
    String numbers = "0123456789";

    StringBuilder sb = new StringBuilder(numbers);

    System.out.println(sb.substring(3)); //3456789
    System.out.println(sb.substring(4, 8)); //4567
    System.out.println(sb.replace(3, 5, "ABCDE")); //012ABCDE56789

    sb = new StringBuilder(numbers);
    System.out.println(sb.reverse()); //9876543210
    sb.reverse(); // Return the original order

    sb = new StringBuilder(numbers);
    System.out.println(sb.delete(5, 9)); //012349
    System.out.println(sb.deleteCharAt(1)); //02349
    System.out.println(sb.insert(1, "One")); //0One2349
}
唯一的區別是 StringBuffer 是線程安全的,並且它的所有方法都是同步的,而 StringBuilder 則不是。這是唯一的功能。Java中的StringBuilder由於方法的非同步性而比StringBuffer更快。因此,大多數情況下,除了多執行緒環境外,Java程式最好使用StringBuilder。我們在三個類別的比較表中總結了所有內容:

String、StringBuffer、StringBuilder

細繩 字串緩衝區 字串產生器
變動性 Immutable(不) mutable(是的) mutable(是的)
可擴展性 final(不) final(不) final(不)
線程安全 是的,由於不變性 是的,由於同步
何時使用 當使用很少被修改的字串時 在多執行緒環境中處理經常修改的字串時 在單線程環境中處理經常修改的字串時
您可以在 JavaRush 課程的 Java 多執行緒任務的第二級中更詳細地研究該主題:
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION