书接上文:
今天分享一下 Groovy 的闭包。基本上,我们可以将闭包视为代码,语句块,它们可以访问周围范围的所有变量或方法,并且可以将这些代码块分配给变量,并将它们传递到其他地方。
def c = { println "hello" }
c()
很简单,闭包只是一个语句,用大括号包含。您可以将其分配给变量,然后像常规方法调用一样调用此闭包。闭包具有一个默认的隐式参数,称为it
。还可以提供自定义的参数。同样,就像方法中的情况一样,闭包的最后一个表达式是闭包的返回值。但是,如果您觉得可读性更高,也可以使用return
关键字。
def square = { it * it }
assert square(3) == 9
def lengthThan = { String s, int i -> return s.size() > i }
//def lengthThan = { String s, int i -> s.size() > i }
assert lengthThan("FunTester", 4) == true
assert lengthThan("Fun", 6) == false
既然我们已经发现了闭包是什么样子,以及如何分配它们并调用它们,我们将了解如何将闭包作为参数传递给另一个方法,因为这就是我们要做的Groovy
在集合上添加的each()
和findAll()
方法。
def log(Closure c) {
println "Calling closure"
def start = System.currentTimeMillis()
println "记录信息: " + c()
def end = System.currentTimeMillis()
println "记录结果成功。(耗时: ${end - start} ms)"
}
log({ return "Groovy is best language!" })
// 可以去掉括号
log { return "Groovy is best language!" }
现在,闭包方面,我们已经小试牛刀。接下来,我们通过对集合使用each()
方法对列表的每个元素调用闭包。我们将打印列表的所有名称:
names.each({ String name -> println name })
names.each { String name -> println name }
names.each { println it }
在使用each()
对每个元素应用闭包之后,由于使用了findAll()
方法,我们将根据过滤器闭包来过滤名称的原始列表,从而创建一个新列表。此方法将查找集合中与作为参数传递的闭包所表示的条件匹配的所有元素。将在每个元素上调用此闭包,并且findAll()
方法将仅返回一个布尔值,该布尔值说明当前值是否匹配。最后,将返回一个包含匹配元素的新列表。该闭包将替换原始Java
类的lengthThan()
方法。
def shortNames = names.findAll { it.size() <= 3 }
Groovy 提供了其他几种此类方法,例如:
现在,该通过应用我们刚刚了解的有关列表和闭包的知识,完成将最初的 Java 类转换为更简洁的 Groovy 类的时候了:
def names = ["Ted", "Fred", "Jed", "Ned"]
println names
def shortNames = names.findAll { it.size() <= 3 }
println shortNames.size()
shortNames.each { println it }