compile()
总是在某个时候调用该方法。这是创建Pattern对象的唯一方法。所以问题是,为什么要显式地调用它?原因之一是您需要对Matcher对象的引用,以便可以使用其方法,例如group(int)
检索捕获组的内容。保留Matcher对象的唯一方法是通过Pattern对象的matcher()
方法,而保留Pattern对象的唯一方法是通过compile()
方法。然后是与String或Pattern类find()
不同的方法,该方法不同于matches()
。
另一个原因是避免一遍又一遍地创建相同的Pattern对象。每次您使用String中正则表达式支持的方法之一(或matches()
Pattern中的静态方法)时,它都会创建一个新的Pattern和一个Matcher。因此,此代码段:
for (String s : myStringList) {
if ( s.matches("\\d+") ) {
doSomething();
}
}
...完全等于:
for (String s : myStringList) {
if ( Pattern.compile("\\d+").matcher(s).matches() ) {
doSomething();
}
}
显然,这做了很多不必要的工作。实际上,与执行实际匹配相比,编译正则表达式和实例化Pattern对象要花很长时间。因此,将这一步骤从循环中拉出来通常是有意义的。您也可以提前创建Matcher,尽管它们并不那么昂贵:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("");
for (String s : myStringList) {
if ( m.reset(s).matches() ) {
doSomething();
}
}
如果您熟悉.NET正则表达式,您可能想知道Java的compile()
方法是否与.NET的RegexOptions.Compiled
修饰符有关;答案是不。Java的Pattern.compile()
方法仅等效于.NET的Regex构造函数。指定Compiled
选项时:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
...它将正则表达式直接编译为CIL字节码,从而使其执行得更快,但是在前期处理和内存使用方面却付出了高昂的代价-将其视为正则表达式的类固醇。Java没有等效的功能。在幕后创建的模式String#matches(String)
与您使用显式创建的模式之间没有区别Pattern#compile(String)
。
(编辑:我原来是说,所有的.NET regex对象缓存,这是不正确由于.NET 2.0,只能用静态的方法,如自动缓存发生。Regex.Matches()
,而不是当你直接调用正则表达式的构造。REF)