java正则关键在pattern编译、matcher状态管理及边界语义:matcher必须每次重新获取;matches()要求全匹配,find()查任意子串,lookingat()仅开头匹配;量词影响回溯行为;默认不支持unicode需显式启用标志。
Java 正则表达式不是“写对就能用”,关键在 Pattern 编译行为、Matcher 状态管理和匹配边界语义——不理解这些,find() 返回 false 或 group() 抛 IllegalStateException 就是常态。
为什么 Pattern.compile() 后必须用 matcher() 获取新 Matcher 实例
Matcher 是有状态对象,每次调用 find()、matches() 会移动内部指针;复用同一个 Matcher 对不同字符串匹配,结果不可靠。
- 错误做法:
Pattern p = Pattern.compile("\d+"); Matcher m = p.matcher("123"); m.find(); // true m = p.matcher("abc"); // 必须重新 matcher(),不能 m.reset("abc") m.find(); // false —— 但你以为只是没匹配到,其实上一次状态可能干扰 - 正确做法:每次匹配前都调用
p.matcher(input),哪怕input是同一个字符串 - 性能提示:如果正则固定且高频使用,
Pattern可静态缓存(线程安全),但Matcher绝对不能缓存复用
matches() vs find() vs lookingAt() 的本质区别
三者不只语义不同,底层锚定逻辑也不同,选错会导致漏匹配或误判。
-
matches():等价于^pattern$,要求整个输入序列完全匹配,开头结尾都被锚定 -
find():在输入中查找**任意位置**的子串匹配,不强制占满全文 -
lookingAt():只从**字符串开头**尝试匹配,不要求结尾,等价于^pattern - 常见陷阱:
"123abc".matches("\d+")→false(因为没吃掉"abc"),但find()就是true
贪婪、勉强、占有量词的实际影响与调试方法
量词后缀(?、+)不只改匹配长度,更决定回溯行为——尤其在嵌套或长文本中,可能引发灾难性回溯(Catastrophic Backtracking)。