的文档Matcher参考实现中的类没有指定的行为appendReplacement
当捕获组不捕获任何内容时的方法(null
) 在替换字符串中指定。虽然行为group
方法很清楚,没有提及appendReplacement
method.
以下是上述案例实施差异的 3 个表现:
- 对于上述情况,参考实现不会附加任何内容(或者我们可以说附加一个空字符串)。
- GNU Classpath 和 Android 的实现附加
null
对于上述情况。
为了简洁起见,省略了一些代码,并由...
.
1) Sun/Oracle JDK、OpenJDK(参考实现)
对于参考实现(Sun/Oracle JDK 和 OpenJDK),代码为appendReplacement
从 Java 6 开始似乎没有改变,当捕获组没有捕获任何内容时,它不会附加任何内容:
} else if (nextChar == '$') {
// Skip past $
cursor++;
// The first number is always a group
int refNum = (int)replacement.charAt(cursor) - '0';
if ((refNum < 0)||(refNum > 9))
throw new IllegalArgumentException(
"Illegal group reference");
cursor++;
// Capture the largest legal group string
...
// Append group
if (start(refNum) != -1 && end(refNum) != -1)
result.append(text, start(refNum), end(refNum));
} else {
参考
- jdk6/98e143b44620
- jdk8/687fd7c7986d
2) GNU 类路径
GNU Classpath 是 Java 类库的完全重新实现,对于以下方面有不同的实现:appendReplacement
在上述情况下。在 Classpath 中,类位于java.util.regex
类路径中的包只是类的包装器gnu.java.util.regex
.
Matcher.appendReplacement calls RE.getReplacement
处理匹配部分的替换:
public Matcher appendReplacement (StringBuffer sb, String replacement)
throws IllegalStateException
{
assertMatchOp();
sb.append(input.subSequence(appendPosition,
match.getStartIndex()).toString());
sb.append(RE.getReplacement(replacement, match,
RE.REG_REPLACE_USE_BACKSLASHESCAPE));
appendPosition = match.getEndIndex();
return this;
}
RE.getReplacement calls REMatch.substituteInto
获取捕获组的内容并直接附加其结果:
case '$':
int i1 = i + 1;
while (i1 < replace.length () &&
Character.isDigit (replace.charAt (i1)))
i1++;
sb.append (m.substituteInto (replace.substring (i, i1)));
i = i1 - 1;
break;
REMatch.substituteInto附加结果REMatch.toString(int)
直接不检查捕获组是否捕获了任何内容:
if ((input.charAt (pos) == '$')
&& (Character.isDigit (input.charAt (pos + 1))))
{
// Omitted code parses the group number into val
...
if (val < start.length)
{
output.append (toString (val));
}
}
And REMatch.toString(int)回报null
当捕获组不捕获时(不相关的代码已被省略)。
public String toString (int sub)
{
if ((sub >= start.length) || sub < 0)
throw new IndexOutOfBoundsException ("No group " + sub);
if (start[sub] == -1)
return null;
...
}
所以在 GNU Classpath 的例子中,null
当替换字符串中指定的捕获组无法捕获任何内容时,将附加到字符串中。
3) Android开源项目-Java核心库
在安卓中,Matcher.appendReplacement调用私有方法appendEvaluated
,这又直接附加结果group(int)
到替换字符串。
public Matcher appendReplacement(StringBuffer buffer, String replacement) {
buffer.append(input.substring(appendPos, start()));
appendEvaluated(buffer, replacement);
appendPos = end();
return this;
}
private void appendEvaluated(StringBuffer buffer, String s) {
boolean escape = false;
boolean dollar = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\\' && !escape) {
escape = true;
} else if (c == '$' && !escape) {
dollar = true;
} else if (c >= '0' && c <= '9' && dollar) {
buffer.append(group(c - '0'));
dollar = false;
} else {
buffer.append(c);
dollar = false;
escape = false;
}
}
// This seemingly stupid piece of code reproduces a JDK bug.
if (escape) {
throw new ArrayIndexOutOfBoundsException(s.length());
}
}
Since Matcher.group(int)
回报null
对于捕获失败的捕获组,Matcher.appendReplacement
追加null
当替换字符串中引用捕获组时。
向您抱怨的两个人很可能是在 Android 上运行他们的代码。