Groovy 闭包学习笔记

时间:2021-07-23 22:40:35

1.      闭包的初步认识

闭包通常用于函数式语言中,它允许执行一个制定好的代码块。

通俗的说,一个闭包就是一个用花括号括起来的语句块,为了传递参数给闭包,闭包有一个可选的参数列表,通过“->”表示列表的结束

闭包的简单实例:

Groovy 闭包学习笔记

面向对象的最高原则是对象有自己的行为和数据,闭包也是对象,其目的是其行为。可以把闭包理解为一个类中的方法。但是始终记住:闭包是由一些代码组成的对象。

2.      闭包的缺省参数it

下面两个closure作用是一样的

[1,2,3].each{println it}
[1,2,3].each{i->println i}

等效的java代码:

List<Integer> list=new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
for(Integer i:list){
System.out.println(i);
}

3. 闭包的用途

         3.1 处理集合,迭代

                   上面的例子都是关于集合的实例

         3.2 处理资源

                 在Java中打开流必须对应一个close来关闭流来释放资源。通过groovy闭包可以实现:

         newFile("D:\\carinfo.txt").eachLine { println it }

eachLine会处理流的打开及关闭。

4. 声明闭包

         4.1 花括号声明

在一个方法调用的后面,放置闭包代码在一对花括号里,闭包的参数和代码通过箭头进行分割。箭头是闭包的参数和代码的分隔指示符。

         4.2 声明变量

使用复制的方式声明闭包,将其赋给一个变量。

         def printer={line -> println line}

         4.3 方法返回值

通过方法返回值

         def Closure getPrinter(){
return {line -> println line}
}

         4.4 引用一个方法作为闭包

         重用已有的声明:一个方法。方法有一个方法体,可选的返回值,能够接受参数,并且能被调用。调用方法:

Groovy 闭包学习笔记

class MethodClosureSample{
int limit

MethodClosureSample(int limit){
this.limit=limit
}

boolean validate(String value){
return value.length()<=limit
}
}

MethodClosureSample first=new MethodClosureSample(6)
MethodClosureSample second=new MethodClosureSample(5)

Closure firstClosure=first.&validate

def words=["long string","medium","short","tiny"]

println(words.find(firstClosure))
println(words.find(second.&validate))

4.5 闭包缺省参数

def adder={x,y=5->return x+y}
println(adder(4,3)) //直接调用
println(adder.call(2)) //call方式调用

5.闭包的调用

 直接调用和使用call方法调用

实例1:

def adder={x,y->return x+y}
println(adder(4,3)) //直接调用
println(adder.call(2,6)) //call方式调用

实例2:从一个方法内部调用一个闭包

def benchmark(repeat,Closure worker){
start=System.currentTimeMillis()
repeat.times{worker(it)}
stop=System.currentTimeMillis()
return stop-start
}

slow=benchmark(10000){(int)it/2}
fast=benchmark(10000){it.intdiv(2)}
println(fast)
println(slow)

6.curry

curry的基本思想是一个多个参数的函数,传递较少的参数给函数来固定一些值。

在groovy中,Closure的curry方法返回当前闭包的一个克隆品,这个克隆品已经绑定一个或多个给定的参数。

def adder={x,y->return x+y}
def addCurry=adder.curry(1)
println(addCurry(6))

一个复杂的例子:

def configurator={format,filter,line->
filter(line)?format(line):null
}

def appender={config,append,line->
def out=config(line)
if(out)append(out)
}

def dateFormatter={line->"${new Date()}:$line"}
def debugFilter={line->line.contains('debug')}
def consoleAppender={line->println line}

def myConf=configurator.curry(dateFormatter,debugFilter)
def myLog=appender.curry(myConf,consoleAppender)

myLog("here is some debug message")
myLog("this will not be printed")

7.变量作用域

def x=0

10.times {x++}

println x

花括号显示了闭包声明的时间,不是执行的时间。在闭包的声明期间,闭包可以对变量x进行读和写操作(没理解这句的意思Groovy 闭包学习笔记)。


闭包在它的生命周期里以某种方式记住了它的工作上下文环境,当调用它时,闭包可以在它的原始上下文中工作。

这种声明周期的上下文需要闭包记住相应地一个引用,而不是一个复制品,如果工作上下文是原始上下文的一个复制品,

从闭包中是没有办法改变原始上下文的。声明周期上下文必须被引用。


在闭包中,this将引用到当前对象,这是对包对象本身。

名称为owner的变量可以获取到声明闭包的对象。

 

8.从闭包返回结果

        闭包最后一个表达式执行的结果,并且这个结果被返回,叫做结束返回,在最后的语句前面的return关键字是可选的。

        使用return关键字从闭包的任何地方返回

        在闭包内使用return关键字和在闭包外使用是有区别的。在闭包内使用return,仅结束闭包的当前计算,例如在list.each中,return不影响闭包在下一个元素时被调用


ps:《Groovy in action》读书笔记