Не должны ли статические шаблоны быть статическими?
Я просто нашел ошибку в некотором коде, который я не писал, и я немного удивлен:
Pattern pattern = Pattern.compile("\\d{1,2}.\\d{1,2}.\\d{4}");
Matcher matcher = pattern.matcher(s);
Несмотря на то, что этот код плохо работает на входных данных, мы получаем (потому что он пытается найти даты в формате 17.01.2011 и возвращает такие вещи, как 10396/2011, а затем разбился, потому что он не может разобрать дату, но действительно не вопрос этого вопроса;) Интересно:
Существует так много примеров по всему миру, где один и тот же шаблон всегда перекомпилируется с использованием Pattern.compile, и я начинаю задаваться вопросом, вижу ли я что-то или нет.
Нет (предполагается, что строка является статической и, следовательно, не динамически построена):
static Pattern pattern = Pattern.compile("\\d{1,2}.\\d{1,2}.\\d{4}");
всегда предпочитает ссылку на нестатический шаблон?
Ответы
Ответ 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
Это классический компромисс между временем и памятью.
Если вы компилируете шаблон только один раз, не вставляйте его в статическом поле.
Если вы измерили, что компиляция шаблонов медленная, предварительно скомпилируйте ее и поместите в статическое поле.