前言
String 是 Java 使用頻率最高的類,也是面試與日常開發的核心考點。本文匯總 20+ 常用方法、內存模型、性能陷阱 及 Java 9+ 新特性,構建完整知識圖譜。
一、 基礎屬性與查詢
| 方法 | 返回值 | 說明 | 示例 |
length() | int | 字符數(char 代碼單元數) | "abc".length() → 3 |
isEmpty() | boolean | 長度為 0(Java 6+) | "".isEmpty() → true |
charAt(int index) | char | 獲取指定位置字符 | "abc".charAt(0) → 'a' |
codePointAt(int index) | int | 獲取 Unicode 碼點(支持增補字符) | "😀".codePointAt(0) → 128512 |
indexOf(String str) | int | 首次出現索引,無則 -1 | "ababa".indexOf("ba") → 1 |
lastIndexOf(String str) | int | 最後出現索引 | "ababa".lastIndexOf("ba") → 3 |
contains(CharSequence s) | boolean | 是否包含子串 (Java 5+) | "abc".contains("b") → true |
startsWith(String prefix) | boolean | 是否以 prefix 開頭 | "abc".startsWith("a") → true |
endsWith(String suffix) | boolean | 是否以 suffix 結尾 | "abc".endsWith("c") → true |
二、 截取與切分
| 方法 | 返回值 | 說明 | 示例 |
substring(int begin) | String | 從 begin 到結尾(含首尾) | "abcd".substring(1) → "bcd" |
substring(int begin, int end) | String | [begin, end) 左閉右開 | "abcd".substring(1,3) → "bc" |
split(String regex) | String[] | 正則分割,尾部空串默認丟棄 | "a,b,".split(",") → ["a","b"] |
split(String regex, int limit) | String[] | limit>0 最多分割 limit 段 | "a,b,c".split(",",2) → ["a","b,c"] |
subSequence(int start, int end) | CharSequence | 等同 substring,實現 CharSequence 接口 | - |
三、 大小寫與空白處理
| 方法 | 說明 | 注意 |
toLowerCase() / toUpperCase() | 使用默認 Locale,可能導致土耳其語 I 问题 | 跨語言環境用 toLowerCase(Locale.ROOT) |
trim() | 移除首尾 ASCII 空白 (≤U+0020) | 不移除全角空格、不換行符 |
strip() / stripLeading() / stripTrailing() | Java 11+,基於 Unicode 空白字符移除 | 推薦替代 trim() |
四、 替換與轉換
| 方法 | 說明 | 示例 |
replace(CharSequence target, CharSequence replacement) | 字面替換,非正則 | "a.b".replace(".", "#") → "a#b" |
replaceAll(String regex, String replacement) | 正則替換 | "a1b2".replaceAll("\\d", "#") → "a#b#" |
replaceFirst(String regex, String replacement) | 替換首次匹配 | "a1b2".replaceFirst("\\d", "#") → "a#b2" |
toCharArray() | 複製字符數組 | 頻繁調用有性能開銷 |
getBytes(Charset charset) | 編碼為字節數組 | 必須指定編碼,避免平台默認編碼差異 |
valueOf(Object obj) | 靜態工廠,null → "null" | String.valueOf(123) → "123" |
五、 比較與匹配
| 方法 | 說明 | 關鍵點 |
equals(Object anObject) | 內容比較,區分大小寫 | 首選比較方式 |
equalsIgnoreCase(String anotherString) | 忽略大小寫比較 | 性能略低於 equals |
compareTo(String anotherString) | 字典序比較 (實現 Comparable) | 返回負/0/正,用於排序 |
compareToIgnoreCase(String str) | 忽略大小寫字典序 | - |
regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) | 區域匹配 | 可指定忽略大小寫 |
matches(String regex) | 全字符串正則匹配 | 等同 Pattern.matches(regex, this) |
六、 Java 9+ 現代 API (必學)
| 方法 | 版本 | 說明 | 示例 |
lines() | 11 | 按行分割為 Stream | "a\nb".lines().count() → 2 |
strip() / stripLeading() / stripTrailing() | 11 | Unicode 感知去空白 | " \u3000a ".strip() → "a" |
isBlank() | 11 | 僅含空白字符(含 Unicode) | " \t\n".isBlank() → true |
repeat(int count) | 11 | 重複拼接 | "ab".repeat(3) → "ababab" |
indent(int n) | 12 | 調整每行縮進 | "a\nb".indent(2) → " a\n b" |
transform(Function f) | 12 | 鏈式轉換 | s.transform(String::toUpperCase).transform(s -> s + "!") |
七、 核心原理與性能陷阱
1. 不可變性與常量池
String s = "abc" → 常量池中創建/複用;
new String("abc") → 堆中強制新建對象(極少需要)。
2. 拼接性能:+ vs StringBuilder vs String.join
- 編譯期常量折疊:
"a" + "b" → "ab" (無開銷);
- 變量拼接:循環內用
StringBuilder,單行表達式 + 編譯器自動優化為 StringBuilder;
- Java 8+
String.join(",", list)、Java 12+ String.transform 更語義化。
3. substring 內存洩漏 (Java 6/7)
早期版本共享底層 char[],長字符串 substring 導致大數組無法回收。Java 7u6+ 已修復(複製數組)。
4. 國際化陷阱
"title".toUpperCase() // TR locale 下 → "TİTLE" (帶點 i)
"TITLE".toLowerCase() // TR locale 下 → "tıtle" (無點 i)
// 導致邏輯判斷失敗
// 修正:toUpperCase(Locale.ROOT) 或 Locale.ENGLISH
八、 實用工具類推薦
org.apache.commons.lang3.StringUtils:isBlank()、join()、truncate()、difference() 等豐富工具;
com.google.common.base.Strings:nullToEmpty()、padStart()、repeat() (Guava);
- JDK 11+ 內置 API 已覆蓋 80%+ 常見場景,優先使用標準庫。
總結
String 看似簡單,實則暗藏 Unicode、Locale、內存模型、版本演進等深層知識。掌握本文速查表,配合 不可變性思維、顯式編碼/Locale、現代 Stream/Builder API,即可寫出正確、高效、可維護的字符串處理代碼。