groovy闭包语法详解(一)

groovy中闭包的用法是后续开发高级DSL的基础,这部分是必须要掌握的。下面开始实践!

闭包与闭包变量

闭包在groovy语言基础模块中被广泛使用。比如数组的基本操作:

在这里插入图片描述

比如,each({ ... })方法,接收一个闭包。闭包是用{ ... }包括的一个独立的可调用的语句执行体。比如要打印列表中每个元素,可这样调用:

def friends = ['Jack', 'Tom', 'John']
friends.each ({
    println "Hello, ${it}"
})

这里声明了一个打印数组当前遍历的元素的闭包。我们说过groovy的方法调用大多数情况下是可以省略()的,下面这种写法更简洁:

friends.each {
    println "Hello, ${it}"
}

对象上的each方法

各种具体类型对Object.each({ ... })方法有各自的重载实现,比如看下面的例子:

在这里插入图片描述

为什么不推荐变量

闭包也可以赋值给一个变量,但是要注意,变量是可以重新赋值的,一般不推荐这样,看下示例:

def friends = ['Jack', 'Tom', 'John']
def sayHello = {
    println "Hello, ${it}"
}
// 将闭包变量作为参数传给一个方法
friends.each sayHello

// 直接调用闭包变量指向的闭包,将其作为函数来调用
sayHello 'xiaojuan'

// 可以改变闭包变量的赋值,现在赋值为一个空闭包,看下发生什么
sayHello = {}

// 下面的调用其实什么都不做,没有任何输出
println '空闭包的调用...'
friends.each sayHello
sayHello 'xiaojuan'

闭包类型的声明

推荐用Closure来声明,一旦这样声明,后续重新赋值为一个非闭包类型,运行时会报错:

Closure c = {}
// 运行时这一行报错:Cannot cast object '123' with class 'java.lang.Integer' to class 'groovy.lang.Closure'
c = 123
// 下面的打印不会被执行
println 'bad!'

闭包与普通代码块的区别

在这里插入图片描述

闭包作为方法参数

定义一个接收闭包参数的方法

// 参数c为闭包类型
def sayHiMethod(Closure c) {
    c.call()
}
// 闭包参数的调用形式
sayHiMethod { println 'Hi!' }

最后一个参数调用的匿名写法

def friends = ['Jack', 'Tom', 'John']
// 作为最后一个参数,可以从圆括号中脱离出来,实现一种匿名写法
friends.each() {
    println "Hello, ${it}"
}
// 从第0个元素开始匹配要找的元素,注意第二个参数是一个对当前元素进行过滤的闭包
def result = friends.findIndexOf(0, { it == 'Tom'})
println result // 输出1
// 也可以从括号中剥离出来,这样写
result = friends.findIndexOf(0) { it == 'John'}
println result // 输出2

这种写法比较怪异,一般还是老老实实写在括号了,看到这样的代码要能理解这种写法即可。

DSL中的闭包参数

模拟对多线程临界区代码的执行,可以封装一个lock方法,将要执行的代码封装在一个闭包中传进来执行:

在这里插入图片描述

转发参数

在定义一个方法时,可以把定义的参数再传给闭包参数进行调用,这就是转发参数。看模拟数据库更新用户信息的一个例子:

// 定义User类
class User {
    String name
}
// 模拟执行数据库事务的方法
def doTransaction(Closure c) {
    println 'begin transaction...'
    c.call()
    println 'commit transaction...'
}
// 更新用户方法
def update(user, Closure c) {
    println "before update name is $user.name"
    // 调用时转发参数
    c.call(user)
    println "after update name is $user.name"
}
// 实例化一个用户
def juan = new User(name: 'juan')
doTransaction {
    update(juan) { user -> user.name = 'xiaojuan' }
}

执行结果:

begin transaction...
before update name is juan
after update name is xiaojuan
commit transaction...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java小卷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值