“静态”模式不应该总是静态的吗?

问题描述 投票:0回答:5

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

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

尽管这个代码在我们得到的输入数据上失败了 (因为它尝试查找 17.01.2011 格式的日期并返回 10396/2011 之类的东西,然后崩溃了,因为它无法解析日期,但是 真的不是这个问题的重点;)我想知道:

  • 不是Pattern.compile的重点之一是速度优化(通过预编译正则表达式)吗?

  • 所有“静态”模式不应该always编译成静态模式吗?

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

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

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

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

java regex static
5个回答
36
投票
  1. 是的,预编译
    Pattern
    的全部目的就是只执行一次。
  2. 这实际上取决于您将如何使用它,但一般来说,存储在
    static
    字段中的预编译模式应该没问题。 (与
    Matcher
    不同,它们不是线程安全的,因此根本不应该存储在字段中,无论是否静态。)

在静态初始值设定项中编译模式的唯一警告是,如果模式未编译并且静态初始值设定项抛出异常,则跟踪错误源可能会非常烦人。这是一个小的可维护性问题,但可能值得一提。


11
投票

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

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

第二,

Pattern.compile()
是重法。始终建议仅初始化一次静态模式(我的意思是未更改或未动态生成的模式)。实现此目的的流行方法之一是将
Pattern.compile()
放入静态初始化程序中。

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


5
投票

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


0
投票

只要类被加载,静态模式就会保留在内存中。

如果您担心内存问题,想要一个一次性的

Pattern
,偶尔使用一次,并且在使用完毕后可以被垃圾回收,那么您可以使用非静态
Pattern


0
投票

这是经典的时间与内存的权衡。 如果您只编译一个模式一次,请不要将其放在静态字段中。 如果您发现编译模式很慢,请预编译它并将其放入静态字段中。

© www.soinside.com 2019 - 2024. All rights reserved.