Подтвердить что ты не робот

Не должны ли статические шаблоны быть статическими?

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

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}");

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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