1、介绍
闭包(Closure)是很多编程语言中很重要的概念,那么Groovy中闭包是什么,官方定义是“Groovy中的闭包是一个开放,匿名的代码块,可以接受参数,返回值并分配给变量”,简而言之,他说一个匿名的代码块,可以接受参数,有返回值,
2、闭包语法
{参数类型 变量名 -> 执行语句} 如果没有参数时,可以简写为 { 执行语句 }
闭包的调用方式有两种:方式一:闭包名.call() 方式二:闭包名()
def test = { println 'hello world' }
// 调用方式有两种
test.call() // 方式一
test() // 方式二
3、闭包中传递参数
def test = { String name -> println "hello world ${name}" } // 需要传入多个参数时,使用逗号进行分隔
test.call("张三") // 方式一
test("zhangsan") // 方式二
// 闭包中有一个默认的参数 叫做 it
def test1 = { println "hello world ${it}" }
test1.call("默认")
// 闭包的返回值
def test2 = { String name -> println "hello world ${name}" } // 闭包没有定义return语句但是还是有返回值,这个返回值就是null
def result = test2.call("返回值")
println(result)
4、闭包与基本类型的结合使用
4.1、使用upto方法求阶乘
int x = fab(5)
println x
int fab(int number) { // 求的阶乘
int result = 1
1.upto(number, { num -> result *= num })
return result
}
4.2、使用down方法求阶乘
int x = fab2(5)
println x
int fab2(int number) {
int result = 1
number.downto(1) {
num -> result *= num
}
return result
}
4.3、使用times方法累计求和
int x = fab3(5)
println x
// 累计求和
int fab3(int number) {
int result = 0
number.times { num -> result += num }
return result
}
5、字符串和闭包的结合使用
5.1、each方法遍历字符串
String str = '1study groovy2'
// each方法遍历字符串
str.each {
// each方法的返回值仍然是调用者的本身
String temp -> println temp
}
5.2、find方法来查找符合条件的第一个
str.find {
String s -> s.isNumber() // find方法的闭包必须是一个布尔类型的返回值
}
5.3、findAll方法找到所有符合条件的元素
str.findAll {
String s -> s.isNumber() // 返回值是一个集合
}
5.4、any方法
any方法的值为布尔类型,只要字符串中的任意元素符合闭包中的条件则为true,反之为false
str.any {
String s -> s.isNumber()
}
5.5、every方法
every方法的值为布尔类型,必须字符串中的每一个元素符合闭包中的条件才能为true,反之为false
str.every {
String s -> s.isNumber()
}
5.6、collect方法
collect方法的返回值为list集合
def list2 = str.collect {
it.toUpperCase()
}
println list2.toListString()
6、闭包中三个重要的变量:this, owner, delegate
this关键字代表闭包定义处的类,owner 关键字代表闭包定义处的类或者对象,delegate关键字代表任意对象,默认与owner一致
// 闭包中定义一个闭包
def nestClosure = {
def innerClosure = {
println "innerClosure this:" + this // 指向的是最近的一个类,脚本类
println "innerClosure owner:" + owner // 指向最近的一个对象
println "innerClosure delegate:" + delegate // 默认与owner保持一致
}
Person p = new Person()
innerClosure.delegate = p // 修改默认的delegate, 修改后delegate与owner指向的对象就不同了
innerClosure.call()
}
nestClosure.call()
7、闭包的委托策略
/* 闭包的委托策略 */
class Student {
String name
def pretty = {"My Name is ${name}"}
String toString() {
pretty.call()
}
}
class Teacher {
String name
}
Student stu = new Student(name: 'salary')
Teacher tea = new Teacher(name: '老师')
// 通过修改delegate实现将Teacher中的name属性替换Student中的属性
stu.pretty.delegate = tea
// 修改策略,默认Closure.OWNER_FIRST
stu.pretty.resolveStrategy = Closure.DELEGATE_FIRST // 如果delegate中没有name这个属性,那他就会在owner中去寻找,Closure.DELEGATE_ONLY,如果delegate中没有name这个属性时,就会报错
println stu.toString()