Разве «статические» шаблоны не должны всегда быть статичными? - PullRequest
22 голосов
/ 08 февраля 2011

Я только что нашел ошибку в каком-то коде, который не написал, и немного удивлен:

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

Несмотря на то, что этот код плохо работает на входных данных, мы получаем (потому что он пытается найти даты в формате 17.01.2011 и возвращает такие вещи, как 10396/2011, а затем падает, потому что он не может разобрать дату, но что действительно не в этом вопрос;) Интересно:

  • не является ли смысл Pattern.compile оптимизацией скорости (путем предварительной компиляции регулярных выражений)?

  • не должны ли все "статические" шаблоны быть всегда скомпилированными в статические шаблоны?

Существует так много примеров, всев Интернете, где один и тот же шаблон всегда перекомпилируется с использованием Pattern.compile , и я начинаю задаваться вопросом, вижу ли я вещи или нет.

Нет (при условии, что строкастатический и, следовательно, не динамически создаваемый):

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

всегда предпочтительнее, чем ссылка на нестатический шаблонсть?

Ответы [ 5 ]

27 голосов
/ 08 февраля 2011
  1. Да, весь смысл предварительной компиляции Pattern заключается в том, чтобы сделать это только один раз.
  2. Это действительно зависит от того, как вы собираетесь его использовать, но в целом предварительно скомпилированные шаблоны, хранящиеся в полях static, должны быть в порядке. (В отличие от Matcher s, которые не являются поточно-ориентированными и поэтому вообще не должны храниться в полях, статических или нет.)

Единственное предостережение, касающееся компиляции шаблонов в статических инициализаторах, заключается в том, что если шаблон не компилируется и статический инициализатор выдает исключение, источник ошибки может быть довольно раздражающим для отслеживания. Это небольшая проблема с ремонтопригодностью, но, возможно, стоит упомянуть.

11 голосов
/ 08 февраля 2011

Во-первых, ошибка в шаблоне заключается в том, что точка (.) Соответствует всему.Если вы хотите сопоставить точку (.), Вы должны экранировать ее в регулярном выражении:

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

Во-вторых, Pattern.compile() - тяжелый метод.Всегда рекомендуется инициализировать статический шаблон (я имею в виду шаблоны, которые не изменяются или не генерируются на лету) только один раз.Один из популярных способов добиться этого - поместить Pattern.compile() в статический инициализатор.

Вы можете использовать другой подход.Например, использование одноэлементного шаблона или использование каркаса, который создает одноэлементные объекты (например, Spring).

3 голосов
/ 08 февраля 2011

Да, компиляция шаблона для каждого использования расточительна, а статическое определение приведет к повышению производительности.См. эту тему SO для аналогичного обсуждения.

0 голосов
/ 08 февраля 2011

Это классический компромисс между временем и памятью.Если вы компилируете Pattern только один раз, не вставляйте его в статическое поле.Если вы измерили, что компиляция Patterns идет медленно, предварительно скомпилируйте ее и поместите в статическое поле.

0 голосов
/ 08 февраля 2011

Статические шаблоны будут оставаться в памяти до тех пор, пока класс загружен.

Если вас беспокоит память и вы хотите выбросить Pattern, который вы используете время от времени и который может собирать мусор, когда вы закончите с ним, тогда вы можете использовать нестатический Pattern.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...