加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Groovy探索之爬出metaClass陷阱

发布时间:2020-12-14 17:05:43 所属栏目:大数据 来源:网络整理
导读:这两天掉入了一个Groovy metaClass的陷阱,好不容易才爬出来。 为了说清楚这个问题,先看几行测试代码 ? void testMetaClass() { def domain = new Domain() domain.metaClass.p = 'v1' assertEquals 'v1',domain.p domain.p = 'v2' assertEquals 'v2',domai

这两天掉入了一个Groovy metaClass的陷阱,好不容易才爬出来。

为了说清楚这个问题,先看几行测试代码

?

    void testMetaClass() {
        def domain = new Domain()
        domain.metaClass.p = 'v1'
        assertEquals 'v1',domain.p

        domain.p = 'v2'
        assertEquals 'v2',domain.p

        domain.metaClass.p = 'v3'
        assertEquals 'v2',domain.p
    }

这是一个已经通过了的测试:

-------------------------------------------------------
Running 1 unit test...
Running test com.grs.GroovyMetaClassTests...null
Empty test suite.
PASSED
Tests Completed in 359ms ...
-------------------------------------------------------

注意Groovy测试代码的最后两行:

domain.metaClass.p = 'v3'
assertEquals 'v2',domain.p

乍一看挺让人纳闷的: 执行

domain.metaClass.p = 'v3'

之后,为什么domain.p的值仍然是'v2'呢?这就是我称之为“陷阱”的地方了。看来Groovy中似乎有这么一条规则:往GroovyObject中第一次通过

domain.metaClass.aProperty = aValue 

的方式往domain中注入aProperty之后, 再执行

domain.metaClass.aProperty = yetAnotherValue 

则无法更改domain.aProperty,而

domain.aProperty = yetAnotherValue 

却可以成功更改。

?

爬出这个陷阱,让我们来看这个问题该如何解决:我怎么才能知道aProperty有没有已经注入呢?换言之,我怎么知道我是应该写成

domain.metaClass.aProperty = yetAnotherValue

呢,还是应该写成

domain.aProperty = yetAnotherValue

呢?

?

我有两个workarounds:

1. 通过try...catch...来检测

class GroovyFieldAccessor {
  static void set(String fieldName,Object obj,Object v) {
    def metaPropAlreadyInjected = true
    try {
        if(obj."$fieldName") {} // do nothing but check if d."$fieldName" will throw an exception.
    } catch(x) {metaPropAlreadyInjected = false}
    if(metaPropAlreadyInjected) {
        obj."$fieldName" = v
    } else {
        obj.metaClass."$fieldName" = v
    }

  }
}

2. 每次都两句一起写:

obj.metaClass."$fieldName" = v
obj."$fieldName" = v

可保万无一失。

?

个人比较喜欢后者,因为它就两行,够简洁。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读