Kotlin和Java String之间的差异与正则expression式分割

如果我们有一个val txt: kotlin.String = "1;2;3;" 并且想把它分成一个数字数组,我们可以尝试以下方法:

 val numbers = string.split(";".toRegex()) //gives: [1, 2, 3, ] 

CharSequence.split的结果中包含尾随的空String

另一方面,如果我们看Java String ,结果是不同的:

 val numbers2 = (string as java.lang.String).split(";") //gives: [1, 2, 3] 

这一次,使用java.lang.String.split ,结果不包括尾随的空String 。 这个行为实际上是给定的相应的JavaDoc:

此方法的工作原理与通过调用给定expression式和极限参数为零的双参数拆分方法一样。 结尾的空字符串因此不包括在结果数组中

在Kotlin的版本中, 0也是这里记录的默认limit参数,但是内部Kotlin在调用 java.util.regex.Pattern::split时将0映射为负值-1

 nativePattern.split(input, if (limit == 0) -1 else limit).asList() 

它似乎正在按预期工作,但我想知道为什么语言似乎限制了Java API,因为不再提供0的限制。

这个实现意味着它是通过在Kotlin中传递limit = 0来实现的java.lang.String.split的行为。 实际上,从我的角度来看,为了使Kotlin的可能选项保持一致,它被删除了。

考虑一个字符串a:b:c:d:和一个模式:

看看我们在Java中可以有什么:

limit < 0[a, b, c, d, ]
limit = 0[a, b, c, d]
limit = 1[a:b:c:d:]
limit = 2[a, b:c:d:]
limit = 3[a, b, c:d:]
limit = 4[a, b, c, d:]
limit = 5[a, b, c, d, ] (与limit < 0
limit = 6[a, b, c, d, ]
...

看起来limit = 0选项是有点独特的:它有尾随:既没有被一个额外的条目取代,也没有被limit < 0limit >= 5 ,也没有保留在最后的结果项目中4)。

在我看来,Kotlin API在这里提高了一致性:在某种意义上,没有特殊情况会丢失关于最后一个分隔符的信息,后面跟着一个空字符串 - 它被保留在最后一个结果项目中的分隔符或作为尾随的空条目。

国际海事组织,Kotlinfunction似乎更符合最不惊讶的原则 。 java.lang.String.split的零极限看起来更像是修改方法语义的特殊值。 负值也是如此,这显然没有直观的意义上的限制 ,没有挖掘Javadoc就不太清楚。