Groovy真值问题: String.split()产生空数组,但是是 'true' ? 怎么回事?
Groovy真值问题: String.split()产生空数组,但是是 'true' ? 怎么回事?
以下是我在groovysh shell中采取的一系列步骤,以展示问题。按照Java SDK的预期,String.split()
=> String[]
。当我将其作为连续表达式的一部分进行评估时:changedDirs.split('\r\n').collect{ ... }
,我的collect
会执行1次,但it
为空。请允许我解释一下:这段代码在Jenkins服务器上运行,众所周知,Jenkins有一种可以称之为groovy方言的运行方式。但是,不管怎样,在本地使用groovysh进行测试时,我确实得到了一个我没有预期的结果:[]
来自String.split()
的结果会被评估为truthy
。
所以,有人能解释一下:
- 为什么下面的groovy代码会对
String.split()
产生truthy
的结果,而对于基本的空[]
不会产生? - Jenkins是否在做一些奇怪的事情?
groovy:000> [] ? 'true' : 'false' ===> false groovy:000> changedDirs = '' ===> groovy:000> changedDirs.split('\r\n') ===> [] groovy:000> changedDirs.split('\r\n') ? true : false ===> true groovy:000> result = changedDirs.split('\r\n') ===> [] groovy:000> result ? true : false ===> true groovy:000> result.class ===> class [Ljava.lang.String; groovy:000> [] as String[] ? true : false ===> false groovy:000>
Groovy中的Truthy问题:String.split()生成空数组,但为什么是“true”?为什么会出现这个问题以及解决方法?
问题的原因是,在Groovy中,调用asBoolean()
方法时,每个非空数组都会被评估为true
,无论数组中的元素是什么。这是Groovy中的“Groovy Truth”规则。
具体来说,在这个例子中,changedDirs.split('\r\n')
生成一个包含一个元素(空字符串)的String[]
数组。因此,result
作为布尔值被评估为true
。
下面是一个例子来说明这个问题:
groovy:000> ([] as String[]).class ===> class [Ljava.lang.String; groovy:000> ([] as String[]) ? true : false ===> false groovy:000> x = ([] as String[]) ===> [] groovy:000> x.dump() ===> <[Ljava.lang.String;> groovy:000> y = "".split(",") ===> [] groovy:000> y.class ===> class [Ljava.lang.String; groovy:000> y.dump() ===> <[Ljava.lang.String;> groovy:000> y ? true : false ===> true groovy:000> y.length ===> 1 groovy:000> x.length ===> 0 groovy:000> y[0].dump() ===> <java.lang.String value= hash=0> groovy:000>
从上面的例子可以看出,空数组x
的长度为0,因此x
被评估为false
;而空数组y
的长度为1,因此y
被评估为true
。
如果我们看一下Java代码的例子,可以看到String.split(pattern)
方法在空字符串的情况下生成一个包含单个元素的数组。
final class Test { public static void main(String[] args) { String[] array = "".split("\r\n"); System.out.println(array.length); // 输出:1 } }
这个问题的解决方法是使用.inspect()
方法来更好地展示问题,而不是使用.dump()
方法。
这是我做的解决方法:(changedDirs ?: null)?.split('\r\n')
,这样就可以得到我想要的结果。
如果你对这个问题感兴趣,这个Stack Overflow的问题可能会有帮助:Why does "split" on an empty string return a non-empty array?