Java的.split()方法角落案例:它们是什么?

fge*_*fge 3 java split

答案,请看下面 - 士气:从不.split()单独打电话; 如果你想要理智的行为,总是给它一个-1的长度参数.但不是0!

对javadoc的Pattern.split()状态如下:

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

见证这段代码:

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

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

现在,引用javadoc,数组应该包含输入的子字符串(引用):

  • "由匹配此模式的另一个子序列终止":好吧,有一个 - 在下划线之前的空字符串(UNDERSCORE显然匹配);
  • 或"在输入序列结束时终止":也有一个:紧跟在下划线之后的空字符串.

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

答案(右下方的解释性文字)

使用a时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);
}
Run Code Online (Sandbox Code Playgroud)

输出:

0 # BUG!
0 # BUG!
2 # BUG!
2 # OK
3 # OK
3 # OK
Run Code Online (Sandbox Code Playgroud)

wch*_*gin 6

从相同的文档:

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

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

确定限制的默认值0:

public String[] split(CharSequence input)
Run Code Online (Sandbox Code Playgroud)

...

此方法的工作方式就像通过调用给定输入序列和limit参数为零的双参数split方法一样.

因此,丢弃空字符串.

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


编辑:清除混淆:根据你的推理,返回的数组是负数限制,是这样的:

[ "" , "" ]
Run Code Online (Sandbox Code Playgroud)

如果使用非正限制,则会删除所有尾随空字符串.最后一个元素是一个空字符串,因此将其删除.然后,你有:

[ "" ]
Run Code Online (Sandbox Code Playgroud)

最后一个元素也是一个空字符串,因此它也被删除.

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


也可以看看: