一. 认识闭包
将代码块作为方法参数进行传递,这种机制就叫做闭包。闭包可以引用在创建闭包的范围中可见的变量。最近关于闭包的讨论也比较多,闭包能使语言更具灵动性,在动态脚本语言中较广泛的支持,如 Perl、Python、Ruby、JavaScript,还有我们的 Groovy。
有些语言能把函数作为参数传递,如 JavaScript 的回调函数,Python,甚至是 C++ 的函数指针。而 Java 在这方面又略逊一筹,需搬动一个匿名的内部类来实现类似的功能,内部类只能访问外部声明为 final 的变量。不过有呼声要在 Java SE 7 中增加闭包特性,让我们试目以待吧。
Groovy 这回大概是从 Ruby 那儿偷得闭包的语法。前面说这么多,其实你看到了就会发现,其实闭包很简单的,不信,请看:
用大括号括起来的,给它一个名字 logo 的那段就是一个闭包(有点像 Java 中的语句块);闭包可以通过执行它的 call() 方法调用,或者直接把它当作一个常规方法对待。闭包也可以没有名字,比如下面要讲的集合方法中用的闭包。
二. 闭包的参数
闭包可以有参数。如果是一个参数的话,该参数就直接映射到名为 it 的变量,如:
如果是多个参数的闭包,则在闭包中用 "->" 把参数列表和实现隔开,如:(当然一个参数也可以这么方式定义的)
我看到这里,怎么越来越觉得闭包那么像 C/C++ 中的宏定义呢?
调用闭包时,如果参数数量不对会抛出 IncorrectClosureArgumentException;不过对于一个参数的闭包,可以少传但不能多传参数,不传参数时,闭包认为 it 为 null。
三. 闭包的传递
闭包在实现上是扩展自 groovy.lang.Closure 类,因为它们是类,所以可以作为参数传递给其他的方法,下面就来看一个例子:
输出为:
Action occured: Status changed
Object saved to the database: Status changed
上面这种用法可用在事件触发、回调 *** 作或策略模式中。
四. 闭包与变量作用域
在 Groovy 中闭包可以访问创建它的上下文中定义的变量,可在闭包中修改;而且闭包内部定义的变量在周围的上下文中也是可见的。看如下代码片断:
执行的结果是:
0.3
0.2
五. 闭包与集合 *** 作
当闭包与集合整合时,它们展现了真正的威力。Groovy 中的 List、Map、String、和 Range 都有接受闭包参数的额外方法,譬如字符串也是字符的集合,也可以这么用。
涉及到的集合 *** 作有 each、collect、inject、find、findAll、every、any。下面以例子来帮助理解这些方法的使用。
注意:上面的闭包传给方法,如果是在 groovyshell 中逐行敲入代码时,起始花括号"{" 必须与调用方法在同一行上,比如说写成下面的方式就有问题:
然而如果你想要在单独一行上指定起始花括号,可以使用下语法(调用方法后加个圆括号):
要是写在 .groovy 文件中或是在 GroovyConsole 中不受这个限制,但是为规范和不致换个环境又出错,还是应该让起起始花括号"{" 与调用方法在同一行。
其实怎么去理解这种要求呢?主要是两点:
其一是为什么我们通常不写这个圆括呢?那是 Groovy 允许方法调用时省略圆括号
还有就是在 groovyshell 下,如果输完方法名,如 each,然后马上回车,就报错
ERROR groovy.lang.MissingPropertyException: Exception evaluating property 'each' for java.util.ArrayList,Reason: groovy
.lang.MissingPropertyException: No such property: each for class: java.lang.Integer
at groovysh_evaluate.run (groovysh_evaluate:1)
...
只有方法名后面加个圆括号,它才知道是参数列表开始,直至匹配的右圆括号结束,或是加了花括,它也知道是一个闭包的开始,直到匹配的花括号结束。
1) collect() 方法利用指定的闭包转换集合的元素
2) inject() 方法,可将前一次的迭代的结果传递给下一次迭代,请看例子:
输出为:
PrevIoUs: 0 - Current: 1
PrevIoUs: 1 - Current: 2
PrevIoUs: 2 - Current: 3
在当前迭代中能知道上一次所迭代的值。inject 接受两个参数,第一次迭代中使用的注入值,和将要使用的闭包。这个闭包也必须定义两个参数,分别为上次迭代的注入值和当前的元素。注意在闭包中必须返回下次迭代中注入的值。否则,就会假设为 null。
为了现好的理解发这个注入语法,我们将上述例子分开来写成如下:
3) find() 方法找到符合闭包中所定义条件的第一次出现的元素,找不到则返回 null
4) findAll() 方法是返回所有符合闭包中所定义条件的元素所组成的集合
5) every() 方法检查集合中是否每一个元素都符合闭包中指定的条件,是则返回 true,否则为 false
6) any() 方法则检查集合中是否有一个元素符合闭包中指定的条件,有则返回 true,否则为 false
参考:1. 《Java 脚本编程语言、框架与模式》第 4 章
总结以上是内存溢出为你收集整理的Unmi 学习 Groovy 之闭包全部内容,希望文章能够帮你解决Unmi 学习 Groovy 之闭包所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)