A Matcher group is available only after a successful match; an unmatched optional group returns null, while a matched empty group returns an empty string.
Java Matcher groups: distinguish absent optional captures from empty text
Keep three states separate
A parser may allow an optional region code after a ticket number. No region, an explicitly empty region, and a nonempty region can mean different things at an API boundary. The capture result must preserve that distinction until validation decides whether an empty region is legal.
Named groups improve reviewability when a pattern has several fields. The program checks both cases by constructing new matchers, then prints whether the optional group is absent or present. Match scope explains the preceding whole-input check.
Validate before reading
Calling group on a matcher without a successful matches or find call throws IllegalStateException. A parser should reject the input before it asks for fields, then convert captured text to typed values with range checks.
Working program
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TicketRegionCapture {
public static void main(String[] args) {
Pattern ticketShape = Pattern.compile("(?<ticket>T-[0-9]{3})(?:\\[(?<region>[A-Z]*)\\])?");
for (String ticketText : new String[] {"T-247", "T-247[]", "T-247[EU]"}) {
Matcher parsed = ticketShape.matcher(ticketText);
if (!parsed.matches()) throw new IllegalArgumentException(ticketText);
String region = parsed.group("region");
System.out.println(region == null ? "absent" : "region='" + region + "'");
}
}
}Output
absent
region=''
region='EU'Cost and ownership
The fixed-width ticket field bounds work here. Each Matcher stores match state; the captured strings allocate from the input. For large or adversarial fields, cap length before matching and reject optional empty fields if the domain forbids them.
Common Mistakes
- Do not collapse null and empty captures into one value without a policy.
- Do not read group before a successful match.
- Do not use a regex shape check as a substitute for identifier lookup.
Read next
Java Matcher.matches and find: whole-input validation versus extraction, Java Matcher.find: account for the scan cursor and zero-length matches, regex unicode flags, Java strings and content equality.
