当没有调用“匹配"方法时,匹配器抛出 IllegalStateException 的基本原理 [英] Rationale for Matcher throwing IllegalStateException when no 'matching' method is called
问题描述
TL;DR
Matcher
的 API?
What are the design decisions behind Matcher
's API?
背景
Matcher
有一种我没有预料到的行为,我找不到充分的理由.API 文档说:
Matcher
has a behaviour that I didn't expect and for which I can't find a good reason. The API documentation says:
一旦创建,匹配器可用于执行三种不同类型的匹配操作:[...]这些方法中的每一个都返回一个指示成功或失败的布尔值.可以通过查询匹配器的状态获得有关成功匹配的更多信息.
Once created, a matcher can be used to perform three different kinds of match operations: [...] Each of these methods returns a boolean indicating success or failure. More information about a successful match can be obtained by querying the state of the matcher.
API 文档进一步说明的是:
What the API documentation further says is:
匹配器的显式状态最初是未定义的;在成功匹配之前尝试查询它的任何部分将导致抛出 IllegalStateException.
The explicit state of a matcher is initially undefined; attempting to query any part of it before a successful match will cause an IllegalStateException to be thrown.
示例
String s = "foo=23,bar=42";
Pattern p = Pattern.compile("foo=(?<foo>[0-9]*),bar=(?<bar>[0-9]*)");
Matcher matcher = p.matcher(s);
System.out.println(matcher.group("foo")); // (1)
System.out.println(matcher.group("bar"));
这段代码抛出一个
java.lang.IllegalStateException: No match found
在(1)
.为了解决这个问题,有必要调用 matches()
或其他方法,使 Matcher
进入允许 group()
的状态.以下工作:
at (1)
. To get around this, it is necessary to call matches()
or other methods that bring the Matcher
into a state that allows group()
. The following works:
String s = "foo=23,bar=42";
Pattern p = Pattern.compile("foo=(?<foo>[0-9]*),bar=(?<bar>[0-9]*)");
Matcher matcher = p.matcher(s);
matcher.matches(); // (2)
System.out.println(matcher.group("foo"));
System.out.println(matcher.group("bar"));
添加对的调用
将(2)
处的matches()Matcher
设置为调用group()
的正确状态.
Adding the call to matches()
at (2)
sets the Matcher
into the proper state to call group()
.
问题,可能没有建设性
为什么这个 API 是这样设计的?当 Matcher
使用 Patter.matcher(String)
构建时,为什么不自动匹配?
Why is this API designed like this? Why not automatically match when the Matcher
is build with Patter.matcher(String)
?
推荐答案
实际上,您误解了文档.再看一下您引用的声明:-
Actually, you misunderstood the documentation. Take a 2nd look at the statement you quoted: -
在成功匹配之前尝试查询它的任何部分将导致抛出 IllegalStateException.
attempting to query any part of it before a successful match will cause an IllegalStateException to be thrown.
如果没有找到匹配项,匹配器可能会在访问 matcher.group()
时抛出 IllegalStateException
.
A matcher may throw IllegalStateException
on accessing matcher.group()
if no match was found.
因此,您需要使用以下测试来实际启动匹配过程:-
So, you need to use following test, to actually initiate the matching process: -
- matcher.matches() //Or
- matcher.find()
以下代码:-
Matcher matcher = pattern.matcher();
只需创建一个 matcher
实例.这实际上不会匹配字符串.哪怕是一场成功的比赛.因此,您需要检查以下条件,以检查是否成功匹配:-
Just creates a matcher
instance. This will not actually match a string. Even if there was a successful match.
So, you need to check the following condition, to check for successful matches: -
if (matcher.matches()) {
// Then use `matcher.group()`
}
如果 if
中的条件返回 false
,则意味着没有匹配.因此,如果您使用 matcher.group()
而不检查此条件,如果未找到匹配项,您将收到 IllegalStateException
.
And if the condition in the if
returns false
, that means nothing was matched. So, if you use matcher.group()
without checking this condition, you will get IllegalStateException
if the match was not found.
假设,如果 Matcher
是按照您所说的方式设计的,那么您必须执行 null
检查以检查是否找到匹配项,以调用matcher.group()
,像这样:-
Suppose, if Matcher
was designed the way you are saying, then you would have to do a null
check to check whether a match was found or not, to call matcher.group()
, like this: -
您认为应该采取的方式:-
// Suppose this returned the matched string
Matcher matcher = pattern.matcher(s);
// Need to check whether there was actually a match
if (matcher != null) { // Prints only the first match
System.out.println(matcher.group());
}
但是,如果你想打印更多的匹配,因为一个模式可以在一个字符串中多次匹配,为此,应该有一种方法告诉匹配器找到下一个匹配.但是 null
检查无法做到这一点.为此,您必须将匹配器向前移动以匹配下一个字符串.因此,在 Matcher
类中定义了各种方法来达到目的.matcher.find()
方法匹配字符串,直到找到所有匹配项.
But, what if, you want to print any further matches, since a pattern can be matched multiple times in a String, for that, there should be a way to tell the matcher to find the next match. But the null
check would not be able to do that. For that you would have to move your matcher forward to match the next String. So, there are various methods defined in Matcher
class to serve the purpose. The matcher.find()
method matches the String till all the matches is found.
还有其他方法,以不同的方式 match
字符串,这取决于您想要如何匹配.所以它最终在 Matcher
类上对字符串进行 matching
.Pattern
类只是创建一个 pattern
来匹配.如果 Pattern.matcher()
要match
模式,那么必须有某种方式来定义各种方式来match
,如 matching
可以有不同的方式.所以,就需要Matcher
类.
There are other methods also, that match
the string in a different way, that depends on you how you want to match. So its ultimately on Matcher
class to do the matching
against the string. Pattern
class just creates a pattern
to match against. If the Pattern.matcher()
were to match
the pattern, then there has to be some way to define various ways to match
, as matching
can be in different ways. So, there comes the need of Matcher
class.
所以,它实际上是这样的:-
Matcher matcher = pattern.matcher(s);
// Finds all the matches until found by moving the `matcher` forward
while(matcher.find()) {
System.out.println(matcher.group());
}
因此,如果在字符串中找到 4 个匹配项,您的第一种方式将仅打印第一个,而第二种方式将打印所有匹配项,通过将 matcher
向前移动以匹配下一个模式.
So, if there are 4 matches found in the string, your first way, would print only the first one, while the 2nd way will print all the matches, by moving the matcher
forward to match the next pattern.
我希望这能说清楚.
Matcher<的文档/code>
类描述了它提供的三个方法的使用,它说:-
The documentation of Matcher
class describes the use of the three methods it provides, which says: -
通过调用模式的匹配器从模式创建匹配器方法.创建后,匹配器可用于执行三种不同的匹配操作的种类:
A matcher is created from a pattern by invoking the pattern's matcher method. Once created, a matcher can be used to perform three different kinds of match operations:
matches 方法尝试匹配整个输入序列与模式相反.
The matches method attempts to match the entire input sequence against the pattern.
lookingAt 方法尝试匹配输入序列,从一开始,反对模式.
The lookingAt method attempts to match the input sequence, starting at the beginning, against the pattern.
find 方法扫描输入序列寻找下一个匹配模式的子序列.
The find method scans the input sequence looking for the next subsequence that matches the pattern.
不幸的是,我找不到任何其他官方消息来源,明确说明了这个问题的为什么和如何.
Unfortunately, I have not been able find any other official sources, saying explicitly Why and How of this issue.
这篇关于当没有调用“匹配"方法时,匹配器抛出 IllegalStateException 的基本原理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!