【问题标题】:Nested Groovy closures produce StackOverflowException嵌套的 Groovy 闭包产生 StackOverflowException
【发布时间】:2016-12-15 17:56:24
【问题描述】:

为什么下面的代码会产生 StackOverflowException?

​Closure c0 = { 
  println "$this $owner $delegate"
  Closure c1 = {
    println "$this $owner $delegate"
  }
  c1()
}

c0()​

输出是

java.lang.StackOverflowError
    at Script1$_run_closure1$_closure2.doCall(Script1.groovy:5)
    at Script1$_run_closure1$_closure2.doCall(Script1.groovy)
    at Script1$_run_closure1.doCall(Script1.groovy:7)
    at Script1$_run_closure1$_closure2.doCall(Script1.groovy:5)
    at Script1$_run_closure1$_closure2.doCall(Script1.groovy)
    at Script1$_run_closure1.doCall(Script1.groovy:7)

【问题讨论】:

    标签: groovy closures


    【解决方案1】:

    StackOverFlowError 是由内部闭包的 ownerdelegate 对象的字符串插值失败引起的。

    您可以通过字符串连接而不是字符串插值来访问它们的值。

    在内部闭包c1中,你可以这样做:

    println "$this " + owner + " " + delegate
    

    这里有一个link to an example,它实现了这个解决方案,还转储了内部和外部闭包的“this”、“owner”和“delegate”的内容,以便您了解它们的不同之处。

    访问链接并单击“执行”按钮查看结果。

    【讨论】:

    • 谢谢你,我猜你回答了我的问题
    【解决方案2】:

    如果你像这样分解脚本,更容易看到发生了什么:

    Closure c0 = {
      println "$this"
      println "$owner"
      println "$delegate"
      Closure c1 = {
        println "$this"      // breakpoint here
        println "$owner"
        println "$delegate"
      }
      c1()
    }
    
    c0()
    

    然后按照指示在 IDE 中设置断点,并通过调试器运行它。然后可以看到,内闭包中的ownerdelegate值,其实就是外闭包。

    现在,通常,当一个对象被插入到 Groovy GString 中时,toString() 方法会被调用,但当插入的对象是一个闭包时,情况并非如此。在那个的情况下,调用顺序是object.call().toString()。因此,闭包c1c0 最终会在无限循环中相互调用。

    在调试器中,您可以单步执行并查看此效果,从第 7 行返回到第 2 行(调用 ownerc0),然后是 3、4、5(定义 @ 987654330@)、10(调用c1)、6、7,然后再回到 2。

    为了防止这种情况,强制闭包更直接地串起来,像这样:

        println (owner as String)
    

    或者这个:

        println (owner.toString())
    

    或者这个:

        println ("" + owner)
    

    (如特雷弗的解决方案)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      • 2019-10-08
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2017-01-19
      • 2020-04-30
      相关资源
      最近更新 更多