闭包其实就是一段用{}包起来的代码,可以通过下面例子了解一下闭包。
//这是一段闭包的代码
def a = {println("hello groovy")}
//可以通过call()调用,也可以直接在后面加()条用
a.call()//hello groovy
a()//hello groovy
//->前面部分是闭包参数 —>后面部分是闭包体(代码)
//这是一个无参的闭包
def b = {-> println("hello groovy")}
b.call()
//有一个入参的闭包
def c= {def str -> println("hello ${str}")}
c.call("groovy")//hello groovy
//有两个入参的闭包
def d= {def str,int age -> println("hello ${str},my age is ${age}")}
d.call("groovy",18)//hello groovy,my age is 18
//默认入参,闭包里面有一个默认参数it,不需要显示声明,用it接受,如果定义了其他入参,该参数失效
def e ={println("hello ${it}")}//hello groovy
e.call("groovy")//hello groovy
//闭包是有返回值的,如果不写返回值,就相当于返回null
def f ={println("hello ${it}")}//hello groovy
def result = f.call("groovy")//hello groovy
println(result)//null
def g ={return ("hello ${it}")}//hello groovy
def res = g.call("groovy")//hello groovy
println(res)//hello groovy
第一个例子是upto
的使用
//从10到20,闭包打印每个数字
10.upto(20){it-> println(it)}
//计算1到100之间数的和
def result=0;
1.upto(100){it -> result+=it}
println(result)//5050
upto
的源码部分内容如下:
public static void upto(Number self, Number to, @ClosureParams(FirstParam.class) Closure closure) {
int self1 = self.intValue();
int to1 = to.intValue();
if (self1 <= to1) {
for (int i = self1; i <= to1; i++) {
//闭包的执行部分
closure.call(i);
}
} else
throw new GroovyRuntimeException("The argument (" + to +
") to upto() cannot be less than the value (" + self + ") it's called on.");
}
第二个例子times
的使用
//执行10次,从0到9
10.times {it -> println(it)}
times
的源码部分内容如下:
public static void times(Number self, @ClosureParams(value=SimpleType.class,options="int") Closure closure) {
for (int i = 0, size = self.intValue(); i < size; i++) {
closure.call(i);
if (closure.getDirective() == Closure.DONE) {
break;
}
}
}
在字符串中常见的一些字符串使用方法。
//便利字符串中的每个字符并打印
def s="hello groovy 2023"
s.each {it -> println(it)}
//找到第一个是数字的字符
println(s.find {it -> it.isNumber()}) // 2
//找到所有是数字的字符
println(s.findAll {it -> it.isNumber()})//[2, 0, 2, 3]
//判断字符串中是否有一个数字
println(s.any {it -> it.isNumber()})//true
//判断字符串中是不是都是数字
println(s.every {it -> it.isNumber()})//false
//将字符串所有字符都转大写
println(s.collect(it-> it.toUpperCase()))//[H, E, L, L, O, , G, R, O, O, V, Y, , 2, 0, 2, 3]
闭包中含有三个内置变量:this
,owner
,delegate
this
:代表定义该闭包的类的实例对象(实例闭包)或者类本身(静态闭包)
owner
:可以和this
用法一样,还可以用作,当闭包中嵌套闭包的时候,这时候owner
就指向定义它的闭包对象
delegate
:含义大多数情况下和owner的含义一样,除非被显示的修改
在Groovy
脚本中定义闭包,那么this
,owner
,delegate
指的都是当前所在脚本的类的对象(当前脚本编译后对应的就是一个脚本类型的类),看下面例子:
package com.dream21th
def a={
println("a->this:"+this)//a->this:com.dream21th.Groovy_study08@576fa0
println("a->owner:"+owner)//a->owner:com.dream21th.Groovy_study08@576fa0
println("a->delegate:"+delegate)//a->delegate:com.dream21th.Groovy_study08@576fa0
}
a.call()
如果定义内部类,那么无论是闭包中还是方法中,this
,owner
,delegate
指代的都是所在类的对象,看下面例子:
class Student{
def b={
println("b->this:"+this)//b->this:com.dream21th.Student@9a0cdb
println("b->owner:"+owner)//b->owner:com.dream21th.Student@9a0cdb
println("b->delegate:"+delegate)//b->delegate:com.dream21th.Student@9a0cdb
}
def test(){
def c={
println("c->this:"+this)//c->this:com.dream21th.Student@9a0cdb
println("c->owner:"+owner)//c->owner:com.dream21th.Student@9a0cdb
println("c->delegate:"+delegate)//c->delegate:com.dream21th.Student@9a0cdb
}
c.call()
}
}
Student student=new Student()//创建一个Student对象
student.b.call()//调用对象中的b闭包
student.test()//调用对象中的test方法
如果定义的内容是静态的,那么this
,owner
,delegate
指代的都是所在类,看下面例子:
class Person{
def static d={
println("d->this:"+this)//d->this:class com.dream21th.Person
println("d->owner:"+owner)//d->owner:class com.dream21th.Person
println("d->delegate:"+delegate)//d->delegate:class com.dream21th.Person
}
def static test(){
def e={
println("e->this:"+this)//e->this:class com.dream21th.Person
println("e->owner:"+owner)//e->owner:class com.dream21th.Person
println("e->delegate:"+delegate)//e->delegate:class com.dream21th.Person
}
e.call()
}
}
Person.d.call() //类直接调用
Person.test()
在这种情况下this
指代的依然是所在类,但是owner
,delegate
指代的就是嵌套的闭包的闭包,看下面例子:
def f={
def g={
println("g->this:"+this)//g->this:com.dream21th.Groovy_study08@7f9738
println("g->owner:"+owner)//g->owner:com.dream21th.Groovy_study08$_run_closure2@141a8ff
println("g->delegate:"+delegate)//g->delegate:com.dream21th.Groovy_study08$_run_closure2@141a8ff
}
g.call()
}
f.call()
无论在什么情况下,this
指代的都是所在类或者类的对象,但是遇到闭包嵌套闭包,owner
,delegate
指代的就是嵌套闭包的闭包。
owner
,delegate
不同的情况:两者的含义在大多数的情况下含义一样,除非它被显示修改。通过下面的例子看
def f={
def g={
println("g->this:"+this)//g->this:com.dream21th.Groovy_study08@baae5
println("g->owner:"+owner)//g->owner:com.dream21th.Groovy_study08$_run_closure2@22cb6a
println("g->delegate:"+delegate)//g->delegate:com.dream21th.Person@1d1c9f2
}
g.delegate=person //显示修改
g.call()
}
f.call()
这种用法使用很少,可以通过下面例子:
package com.dream21th
//定义一个类A
class A{
String name
def a={
"my name is ${name}"
}
String toString(){
a.call()
}
}
//定义一个类B
class B{
String name
}
def a =new A(name:"zhangsan")
def b =new B(name:"lisi")
//${name}取值是从delegate中取值,所以delegate默认情况下指代的是当前A的对象
println(a.toString()) //my name is zhangsan
//修改a的委托对象
//单纯的修改delegate不好用,因为默认情况下delegate委托机制是owner first,所以需要修改委托策略
a.a.delegate=b
println(a.toString()) //my name is zhangsan
a.a.delegate=b
//修改委托策略
a.a.resolveStrategy=Closure.DELEGATE_FIRST
println(a.toString()) //my name is lisi
${name}
取值默认是从delegate
取值,delegate默认和owner的值一样,委托机制也是owner_first优先。所以只修改delegate的值没有用,还需要修改委托策略:delegate_first
。