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 < 0
或limit >= 5
,也没有保留在最后的结果项目中4)。
在我看来,Kotlin API在这里提高了一致性:在某种意义上,没有特殊情况会丢失关于最后一个分隔符的信息,后面跟着一个空字符串 - 它被保留在最后一个结果项目中的分隔符或作为尾随的空条目。
国际海事组织,Kotlinfunction似乎更符合最不惊讶的原则 。 java.lang.String.split
的零极限看起来更像是修改方法语义的特殊值。 负值也是如此,这显然没有直观的意义上的限制 ,没有挖掘Javadoc就不太清楚。