Java正则表达式通过java.util.regex包实现,需注意双反斜杠转义、replaceAll与replace区别、matches与find语义差异,以及预编译Pattern提升性能。
Java 正则表达式不是独立语言,而是通过 
java.util.regex 包(主要是 Pattern 和 Matcher)实现的字符串匹配工具。它和 Perl、JavaScript 的正则语法高度兼容,但有几处关键差异必须注意,否则会匹配失败或抛出 PatternSyntaxException。
这是最常踩的坑:Java 字符串本身会转义一次 \,正则引擎又要再转义一次。比如想匹配一个数字字符 \d,在 Java 字符串里得写成 "\\d";想匹配一个反斜杠字面量 \,得写成 "\\\\"。
常见错误现象:
"\d+" → 编译报错:Invalid escape sequence
"\bword" → 实际匹配的是退格符 + "word",不是单词边界实操建议:
\ 替换成 \\
Pattern.compile() 配合 Pattern.LITERAL 或 Pattern.CASE_INSENSITIVE 标志,减少转义负担String.replaceAll() 内部就是调用 Pattern.compile(regex).matcher(this).replaceAll(replacement),但它要求第一个参数是合法正则——哪怕你只想替换固定字符串,比如 "a.b",其中的 . 也会被当作元字符匹配任意字符。
使用场景:
"\\d+".replaceAll("\\d+", "#"))→ 用 replaceAll()
"a.b" 换成 "x")→ 改用 String.replace("a.b", "x")(不走正则)或 Pattern.quote("a.b") 包装性能影响:每次调用 String.replaceAll() 都会重新编译正则;高频调用建议缓存 Pattern 实例。
matches() 要求整个输入字符串**完全匹配**正则,而 find() 只要在字符串中找到**任意子串匹配**就返回 true。新手常误以为 "abc123".matches("\\d+") 会返回 true,实际是 false,因为整个字符串不全是数字。
典型错误:
str.matches("@") → 应该用 str.matches("^.+@.+$") 或更严谨的模式matcher.matches() → 结果永远 false,应改用 find() + group()
实操建议:
matches()
find()
find() 是游标式遍历,多次调用会移动位置;重用前需 matcher.reset()
重复使用同一正则时,每次都调用 Pattern.compile() 是浪费。尤其在循环、Servlet 请求处理等高频路径中,应将 Pattern 声明为 static final。
public class RegexUtils {
private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");
public static boolean isValidEmail(String email) {
return EMAIL_PATTERN.matcher(email).matches();
}
}
好处:
Pattern.COMMENTS 写带注释的多行正则(需手动去除空白和换行)容易被忽略的地方:正则中的 Unicode 字符类(如 \\p{L})在不同 JDK 版本下行为可能微调,生产环境建议锁定 JDK 小版本并覆盖测试。