"静态"模式不应该是静态的吗?

Gug*_*see 23 java regex static pattern-matching

我刚刚在一些代码中发现了一个我没写过的错误,我有点惊讶:

Pattern pattern = Pattern.compile("\\d{1,2}.\\d{1,2}.\\d{4}");
Matcher matcher = pattern.matcher(s);
Run Code Online (Sandbox Code Playgroud)

尽管这个代码在输入数据上严重失败,但我们得到了(因为它试图找到17.01.2011格式的日期并找回10396/2011之类的内容然后崩溃,因为它无法解析日期,但实际上是 'a'这个问题的重点;)我想知道:

  • 不是点之一Pattern.compile是一个速度优化(由预编译正则表达式)?

  • 不应该将所有"静态"模式总是编译成静态模式吗?

在网络上有很多例子,使用Pattern.compile总是重新编译相同的模式,我开始怀疑我是否看到了东西.

不是(假设字符串是静态的,因此不是动态构造的):

static Pattern pattern = Pattern.compile("\\d{1,2}.\\d{1,2}.\\d{4}");
Run Code Online (Sandbox Code Playgroud)

总是优先于非静态模式参考?

biz*_*lop 27

  1. 是的,预编译a的全部意义Pattern只是做一次.
  2. 这实际上取决于你将如何使用它,但一般来说,存储在static字段中的预编译模式应该没问题.(与Matchers 不同,它不是线程安全的,因此根本不应该存储在字段中,静态或不存在.)

在静态初始化程序中编译模式的唯一警告是,如果模式不编译并且静态初始化程序抛出异常,则错误的来源可能非常令人讨厌.这是一个小的可维护性问题,但值得一提.


Ale*_*exR 11

首先,模式中的错误是因为点(.)匹配所有内容.如果你想匹配点(.)你必须在正则表达式中转义它:

Pattern pattern = Pattern.compile("\\d{1,2}\\.\\d{1,2}\\.\\d{4}");

第二,Pattern.compile()是一种沉重的方法.始终建议仅初始化静态模式(我指的是未动态更改或未动态生成的模式).实现此目的的一种流行方法是将Pattern.compile()静态初始化器放入其中.

您可以使用其他方法.例如,使用单例模式或使用创建单例对象的框架(如Spring).

  • @AlexR如何在静态初始化程序中实例化`Pattern`,例如`static {}`不同于将`Pattern`声明为静态字段,例如`private static final Pattern pattern = Pattern.compile()`? (3认同)

Kal*_*see 5

是的,在每次使用时编译模式是浪费的,而静态地定义它会带来更好的性能。请参阅此 SO 线程以进行类似的讨论。