闭包的样子
闭包,英文叫 Closure,是 Groovy 中非常重要的一个数据类型或者说一种概念了。闭包的历史来源,种种好处我就不说了。我们直接看怎么使用它!
闭包,是一种数据类型,它代表了一段可执行的代码。其外形如下:
def aClosure = {//闭包是一段代码,所以需要用花括号括起来.. String param1,int param2 -> //这个箭头很关键。箭头前面是参数定义,箭头后面是代码 println "this is code" //这是代码,最后一句是返回值, //也可以使用 return,和 Groovy 中普通函数一样 }
简而言之,Closure 的定义格式是:
def xxx = {paramters -> code} //或者 def xxx = {无参数,纯 code} 这种 case 不需要->符号
说实话,从 C/C++ 语言的角度看,闭包和函数指针很像。闭包定义好后,要调用它的方法就是:
闭包对象(参数)
比如:
aClosure.call("this is string",100) 或者 aClosure("this is string",100)
上面就是一个闭包的定义和使用。在闭包中,还需要注意一点:
如果闭包没定义参数的话,则隐含有一个参数,这个参数名字叫 it,和 this 的作用类似。it 代表闭包的参数。
比如:
def greeting = { "Hello,$it!" } assert greeting('Patrick') == 'Hello,Patrick!'
等同于:
def greeting = { it -> "Hello,sans-serif"> 但是,如果在闭包定义时,采用下面这种写法,则表示闭包没有参数!def noparamClosure = { -> true }这个时候,我们就不能给 noparamClosure 传参数了!
noparamClosure ("test") <==报错喔!Closure 使用中的注意点
1.省略圆括号
闭包在 Groovy 中大量使用,比如很多类都定义了一些函数,这些函数最后一个参数都是一个闭包。比如:
public static <T> List<T> each(List<T> self,Closure closure)上面这个函数表示针对 List 的每一个元素都会调用 closure 做一些处理。这里的 closure,就有点回调函数的感觉。但是,在使用这个 each 函数的时候,我们传递一个怎样的 Closure 进去呢?比如:
def iamList = [1,2,3,4,5] //定义一个 List iamList.each{ //调用它的 each,这段代码的格式看不懂了吧?each 是个函数,圆括号去哪了? println it }上面代码有两个知识点:
def testClosure(int a1,String b1,Closure closure){ //do something closure() //调用闭包 }
那么调用的时候,就可以免括号!
testClosure (4,"test",{ println "i am in closure" } ) //红色的括号可以不写..
注意,这个特点非常关键,因为以后在 Gradle 中经常会出现图 7 这样的代码:
经常碰见图 7 这样的没有圆括号的代码。省略圆括号虽然使得代码简洁,看起来更像脚本语言,但是它这经常会让我 confuse(不知道其他人是否有同感),以 doLast 为例,完整的代码应该按下面这种写法:
doLast({ println 'Hello World!' })
有了圆括号,你会知道 doLast 只是把一个 Closure 对象传了进去。很明显,它不代表这段脚本解析到 doLast 的时候就会调用 println 'Hello World!' 。
但是把圆括号去掉后,就感觉好像 println 'Hello World!'立即就会被调用一样!
2.如何确定 Closure 的参数
另外一个比较让人头疼的地方是,Closure 的参数该怎么搞?还是刚才的 each 函数:
如何使用它呢?比如:一个 List 变量 iamList.each{ //调用它的 each 函数,只要传入一个 Closure 就可以了。 println it }看起来很轻松,其实:
- 对于 each 所需要的 Closure,它的参数是什么?有多少个参数?返回值是什么?
我们能写成下面这样吗?
iamList.each{String name,int x -> return x } //运行的时候肯定报错!
所以,Closure 虽然很方便,但是它一定会和使用它的上下文有极强的关联。要不,作为类似回调这样的东西,我如何知道调用者传递什么参数给 Closure 呢?
此问题如何破解?只能通过查询 API 文档才能了解上下文语义。比如下图 8:
图 8 中:
-
each 函数说明中,将给指定的 closure 传递 Set 中的每一个 item。所以,closure 的参数只有一个。
- findAll 中,绝对抓瞎了。一个是没说明往 Closure 里传什么。另外没说明 Closure 的返回值是什么.....。
对 Map 的 findAll 而言,Closure 可以有两个参数。findAll 会将 Key 和 Value 分别传进去。并且,Closure 返回 true,表示该元素是自己想要的。返回 false 表示该元素不是自己要找的。示意代码如图 9 所示:
Closure 的使用有点坑,很大程度上依赖于你对 API 的熟悉程度,所以最初阶段,SDK 查询是少不了的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。