vlambda博客
学习文章列表

问:gradle 里 def 方法为什么不能引用 def 的变量?


点击蓝色小字关注!  关注一下你就不会有bug!

为什么引用不到

在 gradle 中,直接定义一个变量,再定义一个方法,在方法里里是不能引用到该变量的,但在一个闭包中就可以。
1def x = 1
2
3def fun() { println x }
4fun()
5
6android { println x }

如上图所示,fun 无法引用 x,会报错。但 android 闭包中的 x 却能打印出来。这是为什么呢?

1def x = 1
2
3def fun1() { println x }
4
5fun1()
6
7def fun2(Closure closure) { closure() }
8
9fun2 { println x }

运行上面的文件,会报错 Caught: groovy.lang.MissingPropertyException: No such property: x for class: MyGroovy。注释掉 fun1() 后,就可以正常运行。由于在工具栏上的配置中运行时没有生成 build 文件夹,我们手动执行下 compileGroovy 方法,在 app/build/classes/groovy/main 查看编译后的 MyGroovy.class。核心代码是这样的:

 1public Object run() {
2    Reference x = new Reference(1);
3    this.fun1();
4    class _run_closure1 extends Closure implements GeneratedClosure {
5    }
6    return var1[2].callCurrent(thisnew _run_closure1(this, x));
7}
8
9public Object fun1() {
10    CallSite[] var1 = $getCallSiteArray();
11    return var1[3].callCurrent(this, var1[4].callGroovyObjectGetProperty(this));
12}
13
14public Object fun2(Closure closure) {
15    CallSite[] var2 = $getCallSiteArray();
16    return var2[5].call(closure);
17}

run() 方法就是 groovy 脚本执行的方法。可以看出,它先生成了一个 x 的引用,然后调用 fun1、fun2。

fun1 调用时,在它的内部执行了 callGroovyObjectGetProperty 方法,在获取 Groovy 对象的属性。也就是在属性中去寻找 x。

fun2 调用时,是将 x 直接传入了闭包的对象。

因为 x 并不是一个属性,只是一个临时变量,所以 fun1 获取不到,而 fun2 能获取到。

问:gradle 里 def 方法为什么不能引用 def 的变量?怎么引用到

既然是因为属性中没有 x,那我们把 x 加入到属性中就可以了。看一下 gradle 中一个 project 的属性有哪些。一个 project 有 6 种属性的作用域:

  • Project 自己。

  • 这个 project 的附加属性(通过 ext 定义)。

  • 通过插件加入到 Project 的 extensions。

  • 通过插件加入到 Project 的 convention 属性。

  • 这个 project 里的 task。

  • 这个 project 的父 project,递归到根 project。从这里访问到的都是只读的。

所以,将 x 的定义放在 ext 中即可:

1ext { x = 1 } // 或者 ext.x = 1
2
3def fun() { println x }
4
5fun()

现在能正常打印出 x 的值。另外,使用 Script 的 binding 对象也可以实现属性中添加 x。

1binding.setVariable("x"1)
2def fun() { println x }
3fun()


原文:https://blog.csdn.net/Gdeer/java/article/details/83106449
问:gradle 里 def 方法为什么不能引用 def 的变量?
往期精彩回顾


点击左下角阅读原文查看历史经典技术问题汇总,看完顺手走一波PYQ呀~