開發時常見需求:將字串中的雙引號 " 替換為單引號 '。直覺寫法如下:
String content = newsDetail.getContent();
content.replaceAll("\"", "'"); // 看似正確
System.out.println(content); // 輸出卻未變!
明明呼叫了替換方法,結果卻纖毫未動。這不是 Bug,而是 Java 字串不可變性 的經典體現。
查看 String.replaceAll() 實現:
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
追蹤 Matcher.replaceAll():
public String replaceAll(String replacement) {
reset();
boolean result = find();
if (result) {
StringBuffer sb = new StringBuffer(); // 關鍵:建立新容器
do {
appendReplacement(sb, replacement);
result = find();
} while (result);
appendTail(sb);
return sb.toString(); // 返回新字串物件
}
return text.toString(); // 無匹配時返回原字串
}
核心發現:方法內部建立 StringBuffer 組裝結果,最終返回 全新的字串物件。原 content 物件完全未被修改——Java 字串為 final 類別,任何「修改」操作實質皆為建立新物件。
String newContent = content.replaceAll("\"", "'"); // 必須賦值給新變數
System.out.println(newContent); // 正確輸出替換後結果
replace、substring、trim、toUpperCase 等)均返回新物件,原物件不變。StringBuilder(單執行緒)或 StringBuffer(多執行緒)。這不是方法失效,而是對語言核心特性的誤解。Java 以不可變物件換取執行緒安全、字串池優化與安全性,代價是開發者必須養成「接返回值」的肌肉記憶。下次遇到類似「明明改了卻沒變」的靈異現象,請第一時間檢查:是否忽略了返回值?