启动的委托字段在闭包中变为null,Groovy

时间:2015-10-09 09:52:51

标签: groovy annotations closures

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为null。但是如果我删除注释'@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()

1 个答案:

答案 0 :(得分:2)

当您拥有@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()