Java正则表达式模式-编译时间常数还是实例成员?


13

当前,我有几个单例对象,它们在正则表达式上进行匹配,并且Patterns的定义如下:

class Foobar {
  private final Pattern firstPattern =
    Pattern.compile("some regex");
  private final Pattern secondPattern =
    Pattern.compile("some other regex");
  // more Patterns, etc.
  private Foobar() {}
  public static Foobar create() { /* singleton stuff */ }
}

但是前几天有人告诉我这是不好的风格,Pattern应该始终在类级别定义s ,而看起来像这样:

class Foobar {
  private static final Pattern FIRST_PATTERN =
    Pattern.compile("some regex");
  private static final Pattern SECOND_PATTERN =
    Pattern.compile("some other regex");
  // more Patterns, etc.
  private Foobar() {}
  public static Foobar create() { /* singleton stuff */ }
}

这个特定对象的生存期没有那么长,而我使用第一种方法的主要原因是因为,Pattern一旦对象被GC处理,坚持使用s 对我来说就没有意义。

有什么建议/想法吗?

Answers:


18

Java Pattern对象是线程安全的并且是不可变的(其匹配器不是线程安全的)。

这样,如果类的每个实例将使用它们(或再次在该类的另一个方法中),则没有理由使用它们static

使它们成为实例变量,无论它们的生存时间有多短(或多长)都意味着您每次创建类的实例时都要重新编译正则表达式。

这种结构(模式是Matcher对象的工厂)的关键原因之一是将正则表达式编译为其有限的自动机是一项中等成本的操作。但是,人们发现通常在给定的类中一次又一次地使用相同的正则表达式(通过多次调用同一方法或通过该类中的不同位置)。

另一方面,“匹配器”相当轻巧-它指向“模式”中模式的状态以及字符串的字符数组中的位置。


对于单例来说,这没什么大不了的,因为毕竟只有一个实例存在,而且您不会一次又一次地重新创建单例(等等,“单例的寿命并不长” ?这是否意味着你多次实例化它在应用的过程中?)

但是,您会发现某些静态源代码分析器无法识别某些东西是单例的,并且会抱怨您是根据常量为类的每个实例创建模式实例的。

所有这一切的问题在于,这不是一个好选择(对于单例来说也不错),您可能会开始忽略编译器和分析工具告诉您的其他警告(更多有关破损窗口的信息)。

有关:


很棒的答案-是的,我的意思是它只创建过一次/使用过一次,一旦超出范围,就永远做好了。感谢您的后续阅读!
yamafontes
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.