当没有调用“匹配”方法时,Matcher抛出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
at (1)
。要解决这个问题,有必要调用 matches()
或将匹配器
带入一个状态的其他方法允许 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"));
添加对 matches()
(2)
将匹配器
设置为正确状态以调用 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.
匹配器在访问<时可能会抛出 IllegalStateException
code> matcher.group()如果未找到匹配项。
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();
只需创建匹配器
实例。这实际上不匹配字符串。即使有成功的比赛。
因此,您需要检查以下条件,检查是否成功匹配: -
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()`
}
如果中的条件
返回 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.
假设,如果匹配器
的设计方式与你相同说,然后你必须做一个 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());
}
但是,如果你想打印任何进一步的比赛,因为一个模式可以在String中多次匹配,为此,应该有一种方法告诉匹配器找到下一个匹配。但是 null
检查将无法做到这一点。为此,您必须向前移动匹配器以匹配下一个String。因此, 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.
还有其他方法,以不同的方式匹配
字符串,这取决于你想要匹配的方式。因此它最终在 Matcher
类中对字符串执行匹配
。 Pattern
类只是创建一个模式
来匹配。如果 Pattern.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个匹配项,那么第一种方式,将仅打印第一个,而第二个方式将打印所有匹配,通过移动匹配器
前进以匹配下一个模式。
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
类描述了它提供的三种方法的使用,说: -
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:
-
匹配方法尝试将整个输入序列
与模式匹配。
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.
这篇关于当没有调用“匹配”方法时,Matcher抛出IllegalStateException的原理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!