我一直在尝试理解Groovy脚本,但我做的一个示例遇到了意外的StackOverflow。
foo闭包在定义另一个名为bar的闭包之前,将其所有者打印为'Tank'。我希望bar将所有者打印为类似Tank$foo的内容。
class Tank {
def foo = {
println "Owner is $owner"
def bar = {
println " Owner is $owner"
}
bar()
}
static void main(String ...args){
def t = new Tank() ;
t.foo()
}
}
1条答案
按热度按时间h9a6wy2h1#
简单来说,您应该将
bar
方法更改为以下内容:这将阻止
$owner
引用的foo
闭包被求值,因为它将不再是闭包,而是闭包的字符串表示。这就是你在示例中想要实现的。完整答案有点太复杂了,有它的历史......
Groovy中的字符串插值是使用
GString
类实现的。当编译器遇到" Owner is $owner"
时,它首先将该值拆分为不同的片段,其中" Owner is "
保留为string
,而$owner
则指向所谓的值。这就是GString
的示例的构造方式,它是这两个片段的组合。如果我们接着查看Groovy源代码,我们可以看到
GString.toString()
是如何计算的。如果value
是一个闭包那么它就急切地求出这就是为什么在示例中会陷入无限递归的原因。下面是在Groovy源代码中找到的GString.toString()
的片段(请注意c.call(...)
):有趣的是,我还发现当这是第一次介绍和讨论可能改变这种行为。讨论问题仍然是开放的。