我在玩闭包,看到了我无法完全解释的奇怪行为:
groovy:000> ({ println owner })()
groovysh_evaluate@200b6145
===> null
groovy:000> ({ println "${owner}" })()
groovysh_evaluate@2bf75a70
===> null
groovy:000> ({ ({ println owner })() })()
groovysh_evaluate$_run_closure1@10f67a01
===> null
groovy:000> ({ ({ println "${owner}" })() })()
ERROR java.lang.StackOverflowError:
null
at groovysh_evaluate$_run_closure1_closure2.doCall (groovysh_evaluate:2)
at groovysh_evaluate$_run_closure1_closure2.doCall (groovysh_evaluate)
at groovysh_evaluate$_run_closure1.doCall (groovysh_evaluate:2)
at groovysh_evaluate$_run_closure1_closure2.doCall (groovysh_evaluate:2)
at groovysh_evaluate$_run_closure1_closure2.doCall (groovysh_evaluate)
at groovysh_evaluate$_run_closure1.doCall (groovysh_evaluate:2)
<stacktrace repeats>
我认为这与${}
本身就是一个闭包这一事实有关,但我无法确定为什么会发生这种情况。这个问题似乎确实与访问owner
有关,因为我从未在其他变量/表达式中看到过这种情况。有什么想法吗?
当闭包嵌入到GString中时,与嵌入在GString的变量不同,不会在闭包上调用toString()
。在上面看到错误的情况下,owner
是周围的闭包,toString()
不会在闭包上调用。
为了绕过它,必须在owner
上显式调用toString()
,如:
({ ({ println "${owner.toString()}" })() })()
这同样适用于我们构建的嵌套级别的闭包。
({ ({ ({ println "${owner.toString()}" })() })() })()
如果有适当的缩进,它看起来像:
({
({
({
println "${owner.toString()}"
})()
})()
})()
这种行为可以用一个微不足道的例子来解释。
def clos = {return {"hello"}}
println "${clos()}" //prints nothing
println "${clos()()}" //prints hello
错误解释:-
现在来谈谈所面临的错误,如前所述,当闭包嵌入GString中时,不会在闭包上调用toString()
。相反,调用闭包,然后对调用的闭包的结果调用/应用toString()
。意思是:
CCD_ 11相当于CCD_。
在上面的情况下,在调用外部闭包时,它最终通过GString实现["$owner"
]调用自己,并且调用作为递归增长,因此出现了stackerflow错误。
注意:
当应用GString的变量很简单时,可以省略{}
。CCD_ 15与CCD_。只要访问变量的简单属性,就可以执行此操作。"$myVariable.class.name"
是好的(只要myVariable不是映射)。但是当涉及方法调用时,需要大括号"${myVariable.toString()}"