这是一个非常常用且强大的字符串替换方法,但它的使用有一个常见的“陷阱”,理解这个陷阱是正确使用它的关键。

核心概念
String.replaceAll() 方法用于将字符串中所有匹配正则表达式的子字符串替换为指定的替换字符串。
方法签名:
public String replaceAll(String regex, String replacement)
参数:
regex: 一个正则表达式,用来匹配要被替换的子字符串。replacement: 用来替换匹配项的字符串。
返回值:
返回一个新的字符串,其中所有匹配 regex 的部分都被 replacement 替换。

使用示例
示例 1:简单的文本替换
public class ReplaceAllExample {
public static void main(String[] args) {
String text = "Hello Java, hello World, hello everyone!";
// 将所有的 "hello" (不区分大小写) 替换为 "Hi"
// (?i) 是正则表达式中的 flags,表示不区分大小写
String result = text.replaceAll("(?i)hello", "Hi");
System.out.println("原始字符串: " + text);
System.out.println("替换后字符串: " + result);
}
}
输出:
原始字符串: Hello Java, hello World, hello everyone!
替换后字符串: Hi Java, Hi World, Hi everyone!
说明:
replaceAll的第一个参数是正则表达式,虽然在这里我们只是用了一个简单的字符串"hello",但它依然被当作正则表达式来处理。(?i)是一个正则表达式“内联标志”,表示匹配时不区分大小写。
⚠️ 最重要的注意事项:replaceAll 使用的是正则表达式
这是初学者最容易犯错的地方,如果你想在替换字符串中使用特殊字符(如 , \),你必须对它们进行转义,否则它们会被解释为“反向引用”。
反向引用
反向引用允许你在 replacement 字符串中引用正则表达式中的捕获组,捕获组是由 包围的正则表达式部分。

$1引用第一个捕获组$2引用第二个捕获组- 以此类推...
示例 2:反向引用的威力
假设我们想把一个日期字符串 YYYY-MM-DD 的格式改为 DD/MM/YYYY。
public class ReplaceAllGroupExample {
public static void main(String[] args) {
String date = "2025-10-27";
// 正则表达式:捕获 "YYYY", "MM", "DD" 三个组
// (\d{4})-(\d{2})-(\d{2})
// $1 是第一个捕获组 (2025)
// $2 是第二个捕获组 (10)
// $3 是第三个捕获组 (27)
String formattedDate = date.replaceAll("(\\d{4})-(\\d{2})-(\\d{2})", "$3/$2/$1");
System.out.println("原始日期: " + date);
System.out.println("格式化后日期: " + formattedDate);
}
}
输出:
原始日期: 2025-10-27
格式化后日期: 27/10/2025
说明:
(\d{4})-(\d{2})-(\d{2})是一个正则表达式,它将2025-10-27分成了三个捕获组。"$3/$2/$1"是替换字符串,这里的$1,$2,$3不是美元符号和数字,而是反向引用,分别代表第一、第二、第三个捕获组的内容。
常见陷阱:如何替换 或 \ 字符本身?
如果你想在替换字符串中插入一个字面的 符号,你必须用 \$ 来转义它,否则,replaceAll 会尝试将其解释为反向引用, 后面没有紧跟一个数字,或者数字超过了捕获组的数量,就会抛出 IllegalArgumentException。
示例 3:替换 字符(错误的方式)
// 这段代码会抛出异常!
String price = "The price is $100.";
// String result = price.replaceAll("\\$", "USD "); // 错误写法,会抛出异常
// Exception in thread "main" java.lang.IllegalArgumentException: No group 3
// ... (因为replacement中有一个$3,但原始字符串中没有第三个捕获组)
错误原因分析:
replaceAll("\\$", "USD 100")的意图是将 替换为USD 100。- 在
replacement字符串中, 是一个特殊字符,JVM 会尝试将其解释为反向引用,由于你的正则表达式\\$(匹配 字符本身) 没有捕获组, 后面的任何内容都会导致错误。
示例 4:替换 字符(正确的方式)
你必须用 \$ 来转义 。
public class ReplaceAllDollarExample {
public static void main(String[] args) {
String price = "The price is $100.";
// 用 \$ 来表示一个字面的 $ 符号
String result = price.replaceAll("\\$", "USD ");
System.out.println("原始字符串: " + price);
System.out.println("替换后字符串: " + result);
}
}
输出:
原始字符串: The price is $100.
替换后字符串: The price is USD 100.
同理,如果你想替换一个反斜杠 \,你需要用 \\ 来表示一个字面的反斜杠,因为 \ 在 Java 字符串中和正则表达式中都是转义字符。
String path = "C:\\Program Files\\App";
// 将单反斜杠替换为双反斜杠
String result = path.replaceAll("\\\\", "/"); // 注意是四个反斜杠!
System.out.println(result); // 输出: C:/Program Files/App
解释:
- 在 Java 字符串中,
\\表示一个字面的反斜杠\。 replaceAll的第一个参数实际上是\\,这又是一个正则表达式,用来匹配一个字面的反斜杠\。- 在
replacement字符串中, 没有特殊含义,所以直接写即可。
replaceAll vs. replace vs. replaceFirst
| 方法 | 描述 | 第一个参数类型 | 特殊性 |
|---|---|---|---|
replaceAll() |
替换所有匹配项 | 正则表达式 | replacement 中的 和 \ 有特殊含义(反向引用) |
replace() |
替换所有匹配项 | 普通字符串 | 最安全,没有特殊含义,就是纯文本替换 |
replaceFirst() |
替换第一个匹配项 | 正则表达式 | 同 replaceAll,replacement 中的 和 \ 有特殊含义 |
何时使用哪个?
-
当你只想进行纯文本替换,不关心正则表达式时,请始终使用
replace()。- 它更直观、更安全,不容易出错。
text.replace("old", "new")
-
当你需要根据复杂的模式(正则表达式)进行替换时,使用
replaceAll()或replaceFirst()。- 删除所有数字
text.replaceAll("\\d", "") - 只替换第一个出现的单词
text.replaceFirst("\\bword\\b", "term")
- 删除所有数字
replaceAll()是一个基于正则表达式的全局替换方法。- 它的第二个参数
replacement支持反向引用(如$1,$2)。 - 陷阱:如果想在
replacement中使用 或\字符本身,必须用\$和\\进行转义,否则会引发异常或产生非预期结果。 - 对于简单的文本替换,优先使用
String.replace(),因为它更简单、更安全。
