【问题标题】:Initiated delegated field became null in a closure, Groovy启动的委托字段在闭包中变为空,Groovy
【发布时间】:2015-10-09 09:52:51
【问题描述】:

Groovy 版本:2.4.3 JVM:1.8.0_60 供应商:Oracle Corporation 操作系统:Mac OS X

import groovy.transform.*

@Canonical
class A {
    def f() {
        map = [:] //map is not null
        3.times {
            assert map != null // failed, map is null?!
        }
    }

    @Delegate
    Map map
}
new A().f()

当我调用 f() 时,我得到一个断言失败,这意味着 map 为空。但是如果我删除注释'@Delegate',那么就不会有任何问题。或者,如果断言不在闭包中,也没有问题。我的问题是为什么委派字段在闭包内外表现不同?如果是因为闭包中的map不是A类中的同一个对象,为什么在注释删除后它仍然有效?

import groovy.transform.*

@Canonical
class A {
    def f() {
        map = [:]
        3.times {
            assert map != null // No problem, map is not null
        }
    }

    Map map
}
new A().f()

或者

import groovy.transform.*

@Canonical
class A {
    def f() {
        map = [:]
        assert map != null //no problem too
    }

    @Delegate
    Map map
}
new A().f()

【问题讨论】:

    标签: groovy annotations closures


    【解决方案1】:

    当您拥有@Delegate 注释时,您的类本质上成为java.util.Map 的实现,它将其调用委托给它的字段map。断言闭包中对map 的引用被视为this.getAt('map') 调用,而不是对map 字段的引用。由于没有映射到键 map 的值,因此断言失败。

    也许这样会更清楚一点:

    import groovy.transform.*
    
    @Canonical
    class A {
        def f() {
            map = [map:'not null'] // delegated map has key 'map'
            3.times {
                assert map == 'not null'
            }
        }
    
        @Delegate
        Map map
    }
    new A().f()
    

    奇怪之处主要在于断言是在闭包内完成的,其中resolve strategy 指示如何解析引用,其中包括元类的使用。移除闭包,@Delegate 注释不再起作用。

    import groovy.transform.*
    
    @Canonical
    class A {
        def f() {
            assert map != null
        }
    
        @Delegate
        Map map = [:]
    }
    new A().f()
    

    【讨论】:

      猜你喜欢
      • 2013-07-07
      • 2018-10-29
      • 1970-01-01
      • 2019-06-23
      • 2019-10-08
      • 2014-06-20
      • 1970-01-01
      • 1970-01-01
      • 2013-07-14
      相关资源
      最近更新 更多