簡體   English   中英

為什么在字符串中打印閉包的所有者會導致無限遞歸?

[英]Why does printing the owner of a closure in a string cause infinite recursion?

我正在玩閉包,看到這種奇怪的行為,我無法解釋:

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中,則不會在閉包上調用toString() ,而不像GString中嵌入的變量。 在上面你看到錯誤的情況下, 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() 意思是:

"$owner"等同於owner().toString()

在上面的例子中,在調用外部閉包時,它最終通過GString實現[ "$owner" ]調用自身,並且調用增長為遞歸,因此發生堆棧溢出錯誤。

注意:
當您應用GString的變量很簡單時,可以省略{} "${myVariable}""$myVariable"相同。 只要您訪問變量的簡單屬性,就可以這樣做。 "$myVariable.class.name"很好(只要myVariable不是地圖)。 但是當涉及方法調用時需要花括號"${myVariable.toString()}"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM