首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 基礎:String、StringBuffer、StringBuilder 核心機制與效能對比完整指南

     編輯:Java 相關知識

字串處理是 Java 開發最高頻操作。本文深度解析 String 不可變設計動機、字串常量池機制、StringBuffer/StringBuilder 可變實現、線程安全差異、效能基準、傳遞語義、intern() 手動入池,並給出面試高頻題詳細解析與最佳實踐建議。

一、String:不可變設計的藝術

1. 不可變性

public final class String implements ... {
    private final char value[];  // JDK 8: char[];JDK 9+: byte[] + coder
    // 所有「修改」操作實際返回新 String 物件
}
  • final 類不可繼承,final 陣列不可重新指向
  • String s = "a"; s = "b"; 是引用重新指向,非物件修改。兩個 String 物件共存

2. 為什麼不可變?三大核心動機

3. 字串常量池

  • 位置:JDK 7 前在永久代,JDK 7+ 移至堆
  • String s1 = "abc"; String s2 = "abc"; → 同一物件(s1 == s2 為 true)
  • new String("abc") → 強制在堆建立新物件,不使用池中快取(除非調用 intern())

二、StringBuffer vs StringBuilder:可變字串雙雄

動機解析
字串常量池複用編譯期常量、intern() 入池字串共享同一物件。若可變,修改一處影響所有引用,邏輯災難
線程安全不可變物件天然線程安全,無需同步,可自由共享
安全性類載入器、網路連線、檔案路徑等敏感參數用 String,不可變防止惡意篡改

核心差異:同步關鍵字

// StringBuffer
public synchronized StringBuffer append(String str) { ... }

// StringBuilder
public StringBuilder append(String str) { ... }  // 無 synchronized

三、效能基準:拼接字串實測

// 1. String + 拼接(循環中極差)
String s = "";
for (int i = 0; i < 100000; i++) s += "a";  // 每次產生新 String + StringBuilder 物件,O(n²)

// 2. StringBuilder(單執行緒最快)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) sb.append("a"); // O(n)

// 3. StringBuffer(多執行緒共享時)
StringBuffer sbf = new StringBuffer();
// 多執行緒並發 append 安全

結論:單執行緒用 StringBuilder;多執行緒共享緩衝區用 StringBuffer;簡單拼接編譯器優化為 StringBuilder 可直接用 +。

四、面試高頻題深度解析

Q1: 如何比較兩字串?== vs equals()

  • == 比較引用地址
  • equals() 比較內容
  • 常量池字串 == 可能 true,new String() 一定 false
  • 永遠用 equals() 比較內容

Q2: String s = new String("abc") 建立幾個物件?

  1. 常量池中 "abc"(若不存在則建立)
  2. 堆上 new String(...) 新物件,複製常量池內容
  3. 答案:1 或 2 個(視常量池是否已有 "abc")

Q3: 字串作為參數傳遞是值傳遞還是引用傳遞?

  • Java 只有值傳遞。傳遞的是引用的副本
  • 方法內修改參數指向(str = "new")不影響外部引用
  • 但若傳入 StringBuilder,方法內 sb.append() 會影響外部物件(同一物件)
void change(String str) { str += "test"; }  // 區域變數 str 指向新物件,原物件不變
void changeSB(StringBuilder sb) { sb.append("test"); } // 修改同一物件,外部可見

Q4: String.intern() 作用?

  • 若常量池已有內容相同字串,返回池中引用
  • 否則將此字串加入池並返回引用
  • 用途:手動入池節省記憶體、加速 == 比較(慎用)

五、JDK 9+ 優化:Compact Strings

  • private final byte[] value; + byte coder; (LATIN1=0, UTF16=1)
  • 純 ASCII 字串佔用記憶體減半
  • 透明相容,無需程式碼變更

六、最佳實踐總結

特性StringBufferStringBuilder
可變性是(內部 char[]/byte[] 擴容)是
線程安全是(方法 synchronized)否(無同步)
效能較低(同步開銷)高(單執行緒首選)
繼承同父類 AbstractStringBuilder同父類
JDK 版本1.01.5

七、總結

String 不可變是為了常量池複用、線程安全、安全性;StringBuilder 是單執行緒高效拼接首選;StringBuffer 保留給多執行緒共享場景。理解常量池、intern()、參數傳遞語義、JDK 9 Compact Strings,能讓你寫出高效、正確、記憶體友善的字串處理代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景推薦理由
不可變字串常量String常量池複用、線程安全、安全性
單執行緒大量拼接StringBuilder無同步開銷、O(n) 效能
多執行緒共享緩衝區StringBuffer線程安全
簡單拼接 2-3 字串+ 操作符編譯器自動優化為 StringBuilder
需頻繁 == 比較intern() 謹慎使用入池佔用堆記憶體,需權衡
字串參數傳遞理解值傳遞引用副本方法內重新指向不影響外部