Groovy闭包的一些操作

发布时间:2023年12月29日

闭包

? 闭包其实就是一段用{}包起来的代码,可以通过下面例子了解一下闭包。

//这是一段闭包的代码
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
1闭包的一些用法

? 第一个例子是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;
            }
        }
    }
2 闭包在字符串中的使用

? 在字符串中常见的一些字符串使用方法。

//便利字符串中的每个字符并打印
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]
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()
4 闭包中嵌套闭包

? 在这种情况下this指代的依然是所在类,但是ownerdelegate指代的就是嵌套的闭包的闭包,看下面例子:

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指代的都是所在类或者类的对象,但是遇到闭包嵌套闭包,ownerdelegate指代的就是嵌套闭包的闭包。

? ownerdelegate不同的情况:两者的含义在大多数的情况下含义一样,除非它被显示修改。通过下面的例子看

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()
5 闭包委托策略

? 这种用法使用很少,可以通过下面例子:

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

文章来源:https://blog.csdn.net/qq_36305027/article/details/135290840
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。