compile()Метод завжди викликається в якій - то момент; це єдиний спосіб створити об'єкт Pattern. Тож питання справді, чому ви повинні це чітко називати ? Однією з причин є те, що вам потрібна посилання на об'єкт Matcher, щоб ви могли використовувати його методи, як, наприклад, group(int)для отримання вмісту груп захоплення. Єдиний спосіб домогтися об'єкта Matcher - це за допомогою matcher()методу об'єкта Pattern , і єдиний спосіб отримати власність об'єкта Pattern - через compile()метод. Тоді є find()метод, який, на відміну від цього matches(), не дублюється в класах String або 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();
}
}
Очевидно, що це робить багато непотрібної роботи. Насправді, для складання регексу та інстанції шаблону об'єкта може знадобитися більше часу, ніж це для виконання фактичного відповідності. Тому зазвичай має сенс витягнути цей крок з петлі. Ви також можете створити 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).
(EDIT: Спочатку я говорив, що всі об’єкти .NET Regex є кешованими, що невірно. Оскільки. NET 2.0, автоматичне кешування відбувається лише статичними методами, наприклад Regex.Matches(), не при прямому виклику конструктора Regex. Ref )