(2.2.9.3)groovy的闭包

闭包的样子

闭包,英文叫 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++ 语言的角度看,闭包和函数指针很像。闭包定义好后,要调用它的方法就是:

闭包对象.call(参数) 或者更像函数指针调用的方法:

闭包对象(参数)
比如:

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, $it!" }
assert greeting('Patrick') == 'Hello, Patrick!'

但是,如果在闭包定义时,采用下面这种写法,则表示闭包没有参数!

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
}

上面代码有两个知识点:

  • each 函数调用的圆括号不见了!原来,Groovy 中,当函数的最后一个参数是闭包的话,可以省略圆括号。比如
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 函数:

public static <T> List<T> each(List<T> self, Closure closure)

如何使用它呢?比如:

def iamList = [1,2,3,4,5]  //定义一个 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 查询是少不了的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目前包含jar列表如下: ant-1.9.3.jar ant-launcher-1.9.3.jar asm-all-5.0.3.jar bcpg-jdk15on-1.51.jar bcprov-jdk15on-1.51.jar bndlib-2.1.0.jar bsh-2.0b4.jar commons-beanutils-1.7.0.jar commons-cli-1.2.jar commons-codec-1.10.jar commons-codec-1.11-javadoc.jar commons-codec-1.11-sources.jar commons-codec-1.11-test-sources.jar commons-codec-1.11-tests.jar commons-codec-1.11.jar commons-codec-1.4.jar commons-codec-1.6.jar commons-collections-3.2.1.jar commons-collections-3.2.jar commons-httpclient-3.0.1.jar commons-io-1.4.jar commons-io-2.2.jar commons-jexl-2.1.1.jar commons-lang-2.4.jar commons-lang-2.6.jar commons-logging-1.1.1.jar commons-logging-1.1.jar commons-logging-1.2.jar core-3.1.1.jar dom4j-1.6.1.jar ezmorph-1.0.3.jar ezmorph-1.0.4.jar fastjson-1.1.40.jar fluent-hc-4.5.6.jar geronimo-annotation_1.0_spec-1.0.jar gradle-announce-2.3-rc-2.jar gradle-antlr-2.3-rc-2.jar gradle-base-services-2.3-rc-2.jar gradle-base-services-groovy-2.3-rc-2.jar gradle-build-comparison-2.3-rc-2.jar gradle-build-init-2.3-rc-2.jar gradle-cli-2.3-rc-2.jar gradle-code-quality-2.3-rc-2.jar gradle-core-2.3-rc-2.jar gradle-cunit-2.3-rc-2.jar gradle-dependency-management-2.3-rc-2.jar gradle-diagnostics-2.3-rc-2.jar gradle-docs-2.3-rc-2.jar gradle-ear-2.3-rc-2.jar gradle-ide-2.3-rc-2.jar gradle-ide-native-2.3-rc-2.jar gradle-ivy-2.3-rc-2.jar gradle-jacoco-2.3-rc-2.jar gradle-javascript-2.3-rc-2.jar gradle-jetty-2.3-rc-2.jar gradle-language-groovy-2.3-rc-2.jar gradle-language-java-2.3-rc-2.jar gradle-language-jvm-2.3-rc-2.jar gradle-language-native-2.3-rc-2.jar gradle-language-scala-2.3-rc-2.jar gradle-launcher-2.3-rc-2.jar gradle-maven-2.3-rc-2.jar gradle-messaging-2.3-rc-2.jar gradle-model-core-2.3-rc-2.jar gradle-model-groovy-2.3-rc-2.jar gra

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值