-
Enhancement
-
Resolution: Fixed
-
P4
-
19
-
b18
Method String group(String name) has been added in class java.util.regex.Matcher since 1.7 to deal with named-capturing groups.
Unfortunately, interface java.util.regex.MatchResult has not been extended with the same method, even though now it would be possible with a default method without breaking backwards compatibility.
JUSTIFICATION :
Expressions like matcher.toMatchResult().group("MY GROUP") cannot be typechecked when matcher has static type java.util.regex.Matcher, even though class java.util.regex.Matcher defines method String group(String name)
Note that toMatchResult() is very useful if one wants the result to be unaffected by subsequent operations performed upon the matcher; for instance, this is necessary if one has to synchronize the matcher with a character stream with methods Matcher region(int start, int end) or Matcher reset(CharSequence input).
But toMatchResult() is useless if one has to deal with named-capturing groups, because method String group(String name) cannot be invoked on the result of toMatchResult()
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RequestTest {
public static void main(String[] args) {
Matcher matcher = Pattern.compile("(?<NUMBER>[0-9]+)|(?<BLANKS>\\s+)").matcher("42 0");
matcher.lookingAt();
MatchResult res = matcher.toMatchResult();
matcher.region(res.end(), matcher.regionEnd());
// assert res.group("NUMBER").equals("42"); // this line should compile, and assert should succeed
}
}
ACTUAL -
The commented line in the code snippet above cannot be compiled, as expected, since method group(String name) cannot be found in interface java.util.regex.MatchResult
---------- BEGIN SOURCE ----------
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RequestTest {
public static void main(String[] args) {
Matcher matcher = Pattern.compile("(?<NUMBER>[0-9]+)|(?<BLANKS>\\s+)").matcher("42 0");
matcher.lookingAt();
assert matcher.group("NUMBER").equals("42");
MatchResult res = matcher.toMatchResult();
matcher.region(res.end(), matcher.regionEnd());
// assert matcher.group("NUMBER").equals("42"); // throws java.lang.IllegalStateException
// assert res.group("NUMBER").equals("42"); // this line should compile, and assert should succeed
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
One can either use method String group(int group), but this implies giving up using named-capturing groups, or has to resort to reflection (!).
import java.lang.reflect.InvocationTargetException;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RequestReport {
public static void main(String[] args) throws NoSuchMethodException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException, SecurityException {
Matcher matcher = Pattern.compile("(?<NUMBER>[0-9]+)|(?<BLANKS>\\s+)").matcher("42 0");
matcher.lookingAt();
assert matcher.group("NUMBER").equals("42");
MatchResult res = matcher.toMatchResult();
matcher.region(res.end(), matcher.regionEnd());
assert res.group(1).equals("42");
assert res.getClass().getDeclaredMethod("group", String.class)
.invoke(res, "NUMBER").equals("42");
matcher.lookingAt();
assert matcher.group("BLANKS") != null;
}
}
- csr for
-
JDK-8292872 MatchResult should provide values of named-capturing groups
-
- Closed
-
- duplicates
-
JDK-8072984 MatchResult should support named capturing groups
-
- Closed
-
-
JDK-8071479 Stream and lambdafication improvements to j.u.regex.Matcher
-
- Closed
-
-
JDK-8316805 For a regular expression with named groups, you can't extract the names.
-
- Closed
-
-
JDK-8320680 MatchResult.group(String) missing
-
- Closed
-
- relates to
-
JDK-8309515 Stale cached data from Matcher.namedGroups() after Matcher.usePattern()
-
- Closed
-
-
JDK-7032377 MatchResult and Pattern should provide a way to query names of named-capturing groups
-
- Closed
-