compile()Метод всегда вызывается в какой - то момент; это единственный способ создать объект Pattern. Итак, вопрос в том, почему вы должны называть это явно ? Одна из причин заключается в том, что вам нужна ссылка на объект Matcher, чтобы вы могли использовать его методы, например, group(int)для получения содержимого групп захвата. Единственный способ получить объект Matcher - использовать метод объекта Pattern matcher(), а единственный способ получить объект Pattern - использовать этот compile()метод. Затем есть find()метод, который, в отличие от него matches(), не дублируется в классах String или Pattern.
Другая причина - избегать создания одного и того же объекта Pattern снова и снова. Каждый раз, когда вы используете один из методов на основе регулярных выражений в String (или статический matches()метод в Pattern), он создает новый Pattern и новый Matcher. Итак, этот фрагмент кода:
for (String s : myStringList) {
if ( s.matches("\\d+") ) {
doSomething();
}
}
... в точности эквивалентно этому:
for (String s : myStringList) {
if ( Pattern.compile("\\d+").matcher(s).matches() ) {
doSomething();
}
}
Очевидно, это делает много ненужной работы. Фактически, на компиляцию регулярного выражения и создание экземпляра объекта Pattern может уйти больше времени, чем на фактическое сопоставление. Поэтому обычно имеет смысл вытащить этот шаг из цикла. Вы также можете создать Matcher заранее, хотя они и далеко не такие дорогие:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("");
for (String s : myStringList) {
if ( m.reset(s).matches() ) {
doSomething();
}
}
Если вы знакомы с регулярными выражениями .NET, вам может быть интересно, compile()связан ли метод Java с RegexOptions.Compiledмодификатором .NET ; ответ - нет. Pattern.compile()Метод Java просто эквивалентен конструктору Regex в .NET. Когда вы указываете Compiledопцию:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
... он компилирует регулярное выражение непосредственно в байтовый код CIL, что позволяет ему работать намного быстрее, но со значительными затратами на предварительную обработку и использование памяти - думайте об этом как о стероидах для регулярных выражений. Java не имеет эквивалента; нет никакой разницы между шаблоном, который создается за кулисами, String#matches(String)и шаблоном, который вы создаете явно Pattern#compile(String).
(РЕДАКТИРОВАТЬ: я изначально сказал, что все объекты .NET Regex кэшируются, что неверно. Начиная с .NET 2.0, автоматическое кеширование происходит только со статическими методами, например Regex.Matches(), а не при прямом вызове конструктора Regex. Ref )