3

给出答案,见下文——士气:永远不要.split()单独打电话;如果你想要理智的行为,总是给它一个-1的长度参数。但不是0!

javadoc forPattern.split()声明如下:

此方法返回的数组包含输入序列的每个子字符串,这些子字符串由与此模式匹配的另一个子序列终止或在输入序列的末尾终止。

见证这段代码:

private static final Pattern UNDERSCORE = Pattern.compile("_");

public static void main(final String... args)
{
    System.out.println(UNDERSCORE.split("_").length);
}

现在,参考 javadoc,一个数组应该包含输入的子字符串,它们是(引用):

  • “由与此模式匹配的另一个子序列终止”:嗯,有一个 - 下划线之前的空字符串(UNDERSCORE显然匹配);
  • 或“在输入序列的末尾终止”:也有一个:下划线后面的空字符串。

然而,上面的代码打印0. 为什么?这是一个已知的错误?(imnsho 是的,见下文)还有哪些.split()不遵守合同的情况?(再次,见下文

答案(就在这个解释性文本的正下方)

使用 aPattern时,单参数方法等效于使用作为参数.split()调用双参数方法。0

这就是错误所在。如果参数为 0,则从数组“向下”到第一个非空元素的所有空字符串都将从结果中删除

如果在阅读本文之前,您不知道什么是脑残的设计决策,那么现在您知道了。更危险的是,这是默认行为。

解决方案是始终使用该.split()方法的完整形式并给它一个负长度参数。这里选择-1。在这种情况下,.split()行为正常:

private static final Pattern UNDERSCORE = Pattern.compile("_");

public static void main(final String... args)
{
    System.out.println(UNDERSCORE.split("_").length);
    System.out.println(UNDERSCORE.split("__").length);
    System.out.println(UNDERSCORE.split("_x_").length);
    System.out.println(UNDERSCORE.split("_", -1).length);
    System.out.println(UNDERSCORE.split("__", -1).length);
    System.out.println(UNDERSCORE.split("_x_", -1).length);
}

输出:

0 # BUG!
0 # BUG!
2 # BUG!
2 # OK
3 # OK
3 # OK
4

2 回答 2

6

来自相同的文档:

limit参数控制应用模式的次数,因此会影响结果数组的长度。

如果n [the limit] 为零,则该模式将被应用尽可能多的次数,数组可以具有任意长度,并且尾随的空字符串将被丢弃。

限制的默认值确实是0

public String[] split(CharSequence input)

...

此方法的工作方式就像通过使用给定的输入序列和零限制参数调用双参数拆分方法一样。

因此,空字符串被丢弃。

如果你想要它使用UNDERSCORE.split("_", -1),或任何其他负整数。


编辑:为了消除混淆:根据您的推理,如果使用负数限制,返回的数组将是:

[ "" , "" ]

对于非正数限制,所有尾随的空字符串都将被删除。最后一个元素是空字符串,因此将其删除。然后,你有:

[ "" ]

最后一个元素又是一个空字符串,所以它也被删除了。

换句话说,尾随不是指在初始字符串中的尾随,而是在最终数组中的尾随。


也可以看看:

于 2013-06-04T05:03:01.643 回答
0

“由与此模式匹配的另一个子序列终止”:嗯,有一个 - 下划线之前的空字符串(UNDERSCORE 显然匹配);

不,它没有 - 模式之前的空字符串不匹配 '_'

于 2013-06-04T05:06:26.537 回答