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

Java 進階教程:String 類核心機制、不可變性與性能優化

     編輯:Java 相關知識

String 基礎特性

java.lang.String 是 Java 最核心的類之一,特點:

  • 不可變:創建後內容永不改變
  • final 類:不可繼承
  • 字面量池:字符串常量存儲在字符串常量池
  • 無需 new 創建:String s = "abc" 直接創建/復用對象

創建方式與內存差異

方式代碼對象數存儲位置備註
字面量String s = "abc"0 或 1字符串常量池池中有則復用
newString s = new String("abc")1 或 2堆 + 常量池堆中新建,常量池可能有 "abc"
intern()s.intern()0 或 1常量池手動入池,返回池中引用

String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = new String("abc").intern();

System.out.println(s1 == s2); // true - 同一池對象
System.out.println(s1 == s3); // false - 堆 vs 池
System.out.println(s1 == s4); // true - intern 返回池對象
System.out.println(s1.equals(s3)); // true - 內容相等

核心方法速查

分類方法說明
長度/訪問length()字符數 (char 數,非碼點數)
charAt(int index)單字符訪問
codePointAt(int index)碼點訪問 (支持增補字符)
子串/分割substring(int begin, int end)[begin, end) 子串
split(String regex)正則分割
split(String regex, int limit)限制分割數
subSequence(int start, int end)CharSequence 接口方法
查找/匹配indexOf(String str)首次出現索引
lastIndexOf(String str)最後出現索引
contains(CharSequence s)是否包含
matches(String regex)整體正則匹配
大小轉換toUpperCase() / toLowerCase()區域相關,可指定 Locale
trim()去首尾空白 (≤U+0020)
strip() / stripLeading() / stripTrailing()Unicode 感知去空白 (JDK 11+)
替換/構建replace(CharSequence old, new)字面量替換 (非正則)
replaceAll(String regex, String repl)正則替換
format(String fmt, Object... args)靜態格式化
比較/轉換equals(Object obj)內容相等 (== 比較引用)
compareTo(String another)字典序比較 (返回 int)
toCharArray() / getBytes(charset)轉字符/字節數組

不可變性深度解析

實現機制


public final class String implements Serializable, Comparable, CharSequence {
    private final char[] value;  // JDK 8 及之前
    // private final byte[] value; // JDK 9+ Compact Strings
    private final int hash;      // 緩存 hashCode
    // ...
}
  • final char[] value:數組引用不可變,數組內容受保護 (無 setter、無公開訪問)
  • 所有「修改」方法返回新 String 對象

不可變性帶來的優勢

  1. 線程安全:無狀態變更,天然共享
  2. 常量池復用:相同內容只存一份
  3. HashCode 緩存:創建時計算一次,Map/Set 鍵高效
  4. 安全性:網絡/文件路徑、類加載器參數不可被篡改
  5. 字符串拼接優化:編譯器自動用 StringBuilder

「修改」實際創建新對象


String s = "Hello";
s = s.replace("H", "J"); // 新建 "Jello",s 指向新對象
// 原 "Hello" 若無其他引用,變為垃圾

字符串拼接性能陷阱

循環中拼接:災難性性能


// 反例:O(n²) 創建大量中間對象
String result = "";
for (int i = 0; i < 10000; i++) {
    result += i; // 每次 new StringBuilder -> append -> toString
}

正確方式:StringBuilder


// 推薦:預估容量,O(n)
StringBuilder sb = new StringBuilder(10000 * 4);
for (int i = 0; i < 10000; i++) {
    sb.append(i);
}
String result = sb.toString();

編譯器優化:單行拼接自動轉換


String s = "a" + "b" + "c"; // 編譯期常量折疊 -> "abc"
String s2 = a + b + c; // 運行期 -> new StringBuilder().append(a).append(b).append(c).toString()

JDK 9+ Compact Strings 優化

  • 內部存儲改為 byte[] + coder (LATIN1/UTF-16)
  • 純 ASCII 字符串內存減半
  • 大多數西文場景 40-50% 內存節省
  • 完全兼容現有 API

字符串常量池與 intern()


// 運行時動態入池
String dynamic = new String("dynamic").intern();
// 現在常量池中有 "dynamic"
// 後續 "dynamic" 字面量或 intern() 返回同一引用

慎用 intern():常量池在永久代/元空間,過度使用導致 OOM。JDK 7+ 池移至堆,風險降低但仍需節制。

常見陷阱

陷阱錯誤代碼正確代碼
== 比較內容if (s1 == s2)if (s1.equals(s2))
循環拼接s += xStringBuilder
忽略編碼s.getBytes()s.getBytes(StandardCharsets.UTF_8)
正則特殊字符split(".")split("\\.") 或 split(Pattern.quote("."))
substring 內存洩漏 (JDK 6)大字符串 substring 長期持有new String(s.substring(...)) 複製 (JDK 7+ 已修復)

String vs StringBuilder vs StringBuffer

類可變性線程安全性能適用場景
String不可變是-常量、鍵、共享
StringBuilder可變否最快單線程構建字符串
StringBuffer可變是 (同步)較慢多線程構建 (罕用)

總結

String 作為 Java 基石類,其不可變性設計貫穿線程安全、內存優化、安全性、性能優化等核心優勢。掌握「字面量 vs new」、「== vs equals」、「拼接用 StringBuilder」、「顯式編碼」、「JDK 9+ Compact Strings」等要點,是寫出高質量 Java 代碼的基本功。字符串看似簡單,實則蘊含深厚的系統設計智慧。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved