当没有调用“匹配"方法时,匹配器抛出 IllegalStateException 的基本原理 [英] Rationale for Matcher throwing IllegalStateException when no 'matching' method is called

查看:37
本文介绍了当没有调用“匹配"方法时,匹配器抛出 IllegalStateException 的基本原理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆