核心概念
replaceAll 是 Java String 类的一个方法,它的作用是使用给定的正则表达式(Regular Expression)替换字符串中所有匹配的子字符串。

方法签名:
public String replaceAll(String regex, String replacement)
regex: 一个正则表达式,用来匹配需要被替换的子字符串。replacement: 一个字符串,用来替换所有匹配到的部分。
工作原理:正则表达式是关键
replaceAll 的第一个参数是正则表达式,而不是一个简单的普通字符串,这是它和 replace 方法最根本的区别。
replace(String oldChar, String newChar): 将所有oldChar的出现替换为newChar。oldChar是字面量。replaceAll(String regex, String replacement): 将所有匹配regex正则表达式的部分替换为replacement。
示例 1:简单的字符替换
String str = "hello world";
// 使用 replace
String replaced1 = str.replace("l", "x"); // 将 'l' 替换为 'x'
System.out.println(replaced1); // 输出: hexxo worxd
// 使用 replaceAll
// 在正则表达式中,'l' 就代表字符 'l',所以这里效果和 replace 一样
String replaced2 = str.replaceAll("l", "x");
System.out.println(replaced2); // 输出: hexxo worxd
在这个简单例子中,两者效果相同,但 replaceAll 内部使用了更复杂的正则引擎。

常见陷阱与正则表达式元字符
replaceAll 的最大陷阱在于,如果你想在 replacement 中使用一些特殊字符,或者在 regex 中错误地使用了元字符,会导致意想不到的结果。
陷阱 1:regex 中的元字符
正则表达式中有一些特殊字符,被称为“元字符”(Metacharacters),它们有特殊的含义,而不是代表字符本身。
常见的元字符包括:, , , , ^, , , \, , [],
示例 2:错误的元字符使用

假设你想把字符串中的所有点号 替换成 。
String str = "192.168.1.1";
// 错误的写法!
// 在正则表达式中,'.' 代表匹配任意一个字符
String wrongResult = str.replaceAll(".", "-");
System.out.println(wrongResult); // 输出: -------- (一共10个'-',因为字符串有10个字符,都被匹配了)
正确的写法:
需要对元字符进行“转义”,即在前面加上反斜杠 \。
String str = "192.168.1.1";
// 正确的写法,使用 \\ 来转义 .
String correctResult = str.replaceAll("\\.", "-");
System.out.println(correctResult); // 输出: 192-168-1-1
为什么是 \\. 而不是 \.?
因为在 Java 的字符串字面量中,反斜杠 \ 本身就是一个转义字符,为了在字符串中得到一个 \ 字符,你需要写成 \\,要表示正则表达式中的 \.,你需要在 Java 字符串中写成 "\\\\"。
陷阱 2:replacement 中的特殊引用符
在 replacement 字符串中,可以使用 符号来引用正则表达式中的“捕获组”(Capturing Groups)。
$0: 代表整个匹配的字符串。$1,$2, ...: 代表第一个、第二个...捕获组匹配的内容。
示例 3:使用捕获组进行高级替换
假设我们想把一个日期字符串 YYYY-MM-DD 的格式改成 DD/MM/YYYY。
String dateStr = "2025-10-27";
// 使用捕获组
// (\d{4}) 匹配并捕获年份
// (\d{2}) 匹配并捕获月份
// (\d{2}) 匹配并捕获日期
String newDateStr = dateStr.replaceAll("(\\d{4})-(\\d{2})-(\\d{2})", "$3/$2/$1");
System.out.println(newDateStr); // 输出: 27/10/2025
这里的 $1 对应 (\\d{4}),$2 对应 (\\d{2})(月份),$3 对应 (\\d{2})(日期)。
陷阱:replacement 中有 但不是引用组
如果你想在替换字符串中包含一个字面量的 ,你需要对它进行转义,写成 \$。
String price = "The price is $100.";
// 错误:$1 会被解释为第一个捕获组,但这里没有捕获组
// String wrong = price.replaceAll("\\$", "USD"); // 会抛出异常: Illegal group reference
// 正确:对 $ 进行转义
String correct = price.replaceAll("\\$", "USD");
System.out.println(correct); // 输出: The price is USD100.
replaceAll vs. replace
| 特性 | replaceAll(String regex, String replacement) |
replace(char/CharSequence old, char/CharSequence new) |
|---|---|---|
| 参数类型 | regex (正则表达式), replacement (字符串) |
old (字符或字符串), new (字符或字符串) |
| 功能 | 使用正则表达式查找并替换所有匹配项。 | 使用字面量查找并替换所有匹配项。 |
| 性能 | 通常较慢,因为需要解析和编译正则表达式。 | 通常非常快,是简单的字符/字符串替换。 |
| 使用场景 | 需要复杂的模式匹配时(如:删除所有非数字字符、替换特定格式等)。 | 简单的、直接的字符或子字符串替换。 |
| 示例 | s.replaceAll("\\s+", " ") (将多个空格合并为一个) |
s.replace('a', 'b') (将所有 'a' 换成 'b') |
实用代码示例
示例 1:清理电话号码格式
String messyPhone = "我的电话是 123-4567-8910,或者 9876 5432。";
// 移除所有非数字字符
String cleanPhone = messyPhone.replaceAll("[^0-9]", "");
System.out.println(cleanPhone); // 输出: 1234567891098765432
[^0-9] 是一个正则表达式,表示“匹配任何一个不是 0 到 9 数字字符的字符”。
示例 2:移除 HTML 标签(简单版)
String html = "<p>这是一个<b>重要</b>的段落。</p>";
// <.*?> 是一个非贪婪匹配,匹配 < 和 > 之间的任意字符,但尽可能少地匹配
String plainText = html.replaceAll("<.*?>", "");
System.out.println(plainText); // 输出: 这是一个重要的段落。
注意:这个方法非常基础,对于复杂的嵌套 HTML 标签会失效,在生产环境中,应使用专门的 HTML 解析器(如 Jsoup)。
示例 3:标准化字符串中的空白
String str = " Hello, World! ";
// \s 匹配任何空白字符(空格, 制表符, 换行等)
// + 表示匹配前面的元素一次或多次
String normalizedStr = str.replaceAll("\\s+", " ").trim();
System.out.println(normalizedStr); // 输出: Hello, World!
replaceAll使用正则表达式,这是它最核心的特点。- 注意转义:在
regex中,元字符(如 )需要用\\转义,在replacement中, 需要用\$转义。 - 性能考虑:对于简单的字符串替换,优先使用
replace,因为它更快。 - 功能强大:掌握正则表达式后,
replaceAll是一个非常强大的文本处理工具,可以完成复杂的查找和替换任务。
希望这个详细的解释能帮助你完全理解 Java 的 replaceAll 方法!
