如果我们有val txt: kotlin.String = "1;2;3;"
并希望将其拆分为数字数组,我们可以尝试以下方法:
val numbers = string.split(";".toRegex())
//gives: [1, 2, 3, ]
结尾的空String
包含在CharSequence.split
的结果中。
另一方面,如果我们查看Java String
,结果会有所不同:
val numbers2 = (string as java.lang.String).split(";")
//gives: [1, 2, 3]
这一次,使用java.lang.String.split
,结果不包括尾随空String
。实际上,这种行为是在给定相应的JavaDoc:
此方法的作用就像通过使用给定表达式和 limit参数为零调用双参数split方法一样。 因此,结果数组中不包含尾随空字符串。
在Kotlin的版本中,0
也是默认的limit
参数,记录为here,但内部Kotlin将0
映射为负值-1
当java.util.regex.Pattern::split
为called时:
nativePattern.split(input, if (limit == 0) -1 else limit).asList()
它似乎按预期工作但我想知道为什么该语言似乎限制了Java API,因为不再提供0
的限制。
答案 0 :(得分:11)
实现意味着通过传递在Kotlin中丢失的java.lang.String.split
来实现limit = 0
的行为。实际上,从我的观点来看,它被删除以实现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
替换,也不会保留在最后得到的项目(与1..4中的limit
一样。)
在我看来,Kotlin API在这里提高了一致性:在某种意义上,没有特殊情况会丢失关于最后一个分隔符后跟一个空字符串的信息 - 它作为最后一个分隔符留在原地结果项目或作为尾随空条目。
IMO,Kotlin函数似乎更适合principle of least astonishment。相反,java.lang.String.split
中的零限制看起来更像是修改方法语义的特殊值。负值也是如此,显然没有直观意义上的限制,如果不挖掘Javadoc就不太清楚。