答案,请参见下文 - 士气:从不单独打电话给.split()
;如果你想要理智的行为,总是给它一个-1的长度参数。但不是0!
javadoc for Pattern.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 yes,见下文).split()
不遵守合同的其他情况是什么? (再次,见下文)
答案(右下方的解释性文字)
使用Pattern
时,单参数.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
答案 0 :(得分:6)
来自相同的文档:
limit
参数控制模式的应用次数,因此会影响结果数组的长度。如果 n [限制]为零,那么模式将被应用尽可能多次,数组可以具有任何长度,并且尾随空字符串将被丢弃。
限制的默认值确实是0
:
public String[] split(CharSequence input)
...
此方法的工作方式就像通过调用给定输入序列和limit参数为零的双参数split方法一样。
因此,空字符串被丢弃。
如果您需要使用UNDERSCORE.split("_", -1)
或任何其他负整数。
编辑:为了清除混淆:根据你的推理,返回的数组会有一个负数限制,就是:
[ "" , "" ]
如果使用非正限制,则会删除所有尾随空字符串。最后一个元素是一个空字符串,因此将其删除。然后,你有:
[ "" ]
最后一个元素也是一个空字符串,因此它也会被删除。
换句话说,尾随不是指在初始字符串中尾随,而是在最终数组中尾随。
另见:
答案 1 :(得分:0)
“由与此模式匹配的另一个子序列终止”:好吧,有一个 - 在下划线之前的空字符串(UNDERSCORE明显匹配);
不,它没有 - 模式之前的空字符串与'_'
不匹配