Groovy强制转换表现不一致

时间:2012-09-14 00:28:36

标签: groovy

我今天碰到了一大块代码,等同于:

[["asdf"]].each {String str -> println str}

println (["asdf"] as String)

将它放入groovy控制台(groovysh),你就会看到它出来了:

asdf

[asdf]

有人可以解释为什么输出会有差异吗?

2 个答案:

答案 0 :(得分:5)

Groovy将解包List,如果这意味着它将适合您在闭包中定义的类型。

如果您没有定义类型(或将其设置为List),它将按预期运行:

// Both print '[a]'
[['a']].each { it -> println it }
[['a']].each { List it -> println it }

但是,如果您定义了一个类型,它将尝试解包该列表并将内容应用于定义的参数,因此:

// Prints 'a'
[['a']].each { String it -> println it }

将其想象为java中的varargs,或者在Groovy中使用closure( *it )调用闭包

它实际上非常有用,因为你可以做以下事情:

// Tokenize the strings into 2 element lists, then call each with these
// elements in separate variables
['a=b', 'b=c']*.tokenize( '=' )
               .each { key, value ->
  println "$key = $value"
}

答案 1 :(得分:1)

第一个输出

我不确定,但似乎Groovy会尝试将闭包应用于列表的单个元素,如果只有一个。

请注意:

[["asdf"]].each {String str -> println str }

相当于:

Closure c = { String s -> println s }
c(["asdf"])

并且这些测试表明了经验证据:

Closure c = { String s -> println s }

println "c test"
try { c(["asdf","def"]) } catch(Exception ex) { println "no" }
try { c(123) } catch(Exception ex) { println "no" }
try { c([]) } catch(Exception ex) { println "no" }
// this works:
try { c(["asdf"]) } catch(Exception ex) { println "no" }

Closure d = { Integer i -> println i }

println "d test"
try { d([22,33]) } catch(Exception ex) { println "no" }
try { d("abc") } catch(Exception ex) { println "no" }
try { d([]) } catch(Exception ex) { println "no" }
// this works:
try { d([22]) } catch(Exception ex) { println "no" }

第二个输出

请注意:

println (["asdf"] as String)

可能与此相当:

List<String> list = ["asdf"]
println list.toString()