String 提供三個替換方法:replace、replaceAll、replaceFirst。它們在參數型別、正則支援與特殊字元處理上有關鍵差異,誤用極易導致 Bug。本文透過實例深入剖析。
| 方法 | 第一參數 | 第二參數 | 替換範圍 |
|---|---|---|---|
replace(CharSequence, CharSequence) | 字面字串 | 字面字串 | 所有匹配項 |
replaceAll(String regex, String replacement) | 正則表達式 | 字串(支援 $n 群組引用) | 所有匹配項 |
replaceFirst(String regex, String replacement) | 正則表達式 | 字串(支援 $n 群組引用) | 第一個匹配項 |
String src = "abac";
// 期望將 'a' 替換為 '\a'
System.out.println(src.replace("a", "\\a")); // \ab\ac 正確
System.out.println(src.replaceAll("a", "\\a")); // abac 錯誤!
System.out.println(src.replaceFirst("a", "\\a")); // abac 錯誤!
原因:replaceAll/First 的第二參數視 \ 為轉義字元,$ 為群組引用。要輸出字面反斜線,需雙重轉義:"\\\\a"。
// 將 'a' 後緊鄰的字元重複一次:a(b) -> bb
"abac".replaceAll("a(\\w)", "$1$1"); // bbcc
"abac".replaceFirst("a(\\w)", "$1$1"); // bbac
// 替換為字面 '$' 需轉義
"abac".replaceAll("a", "\\$"); // $b$c
Java 5+ 提供 Matcher.quoteReplacement(String) 自動處理替換字串中的特殊字元:
String replacement = Matcher.quoteReplacement("\\a"); // 回傳 "\\\\a"
"abac".replaceAll("a", replacement); // 正確輸出 \ab\ac
replace,效能最好且無轉義煩惱。replaceAll/First,並善用 Matcher.quoteReplacement 處理替換字串。replaceFirst。Pattern 並使用 Matcher 手動控制。三個方法雖名稱相似,但語意截然不同。記住:replace 是字面替換,replaceAll/First 是正則替換且替換字串有特殊語意。善用 Matcher.quoteReplacement 可避免 90% 的轉義 Bug。