groovy闭包

你想理解 Groovy 中闭包(Closure)的核心概念,并通过实用示例掌握它的用法 ------ 闭包是 Groovy 最核心的特性之一,本质是「可复用的代码块」,能作为参数传递、赋值给变量,还能访问外部作用域的变量,比 Java 的 Lambda 更灵活。下面我会先讲核心概念,再用多个高频场景的示例帮你吃透闭包。

一、闭包的核心概念

1. 定义

闭包是 Groovy 中一种特殊的代码块,用 {} 包裹,可包含参数和执行逻辑,语法格式:

groovy

复制代码
// 格式1:无参数闭包
{ 代码逻辑 }

// 格式2:有参数闭包(参数写在箭头前,多个参数用逗号分隔)
{ 参数1, 参数2 -> 代码逻辑 }

// 格式3:单参数简化(省略参数和箭头,用默认变量 it 指代参数)
{ 代码逻辑 }  // 等价于 { it -> 代码逻辑 }
2. 核心特性
  • 可赋值给变量:闭包本身是对象,可像普通变量一样赋值、传递;
  • 访问外部变量:闭包能访问定义它的外部作用域的变量(无需传参);
  • 灵活的参数 :支持默认参数、可变参数,单参数可省略声明(用 it);
  • 作为方法参数:Groovy 集合、IO 等 API 大量使用闭包作为参数,简化代码。

二、闭包的基础示例(从简单到复杂)

示例 1:基础闭包 ------ 赋值给变量并执行

这是最基础的用法,闭包赋值给变量后,通过 ()call() 执行:

groovy

复制代码
// 1. 无参数闭包
def sayHello = { println "Hello Groovy!" }
sayHello()  // 执行方式1:直接加括号,输出 "Hello Groovy!"
sayHello.call()  // 执行方式2:call() 方法,效果相同

// 2. 单参数闭包(用默认变量 it)
def printNum = { println "数字:${it}" }
printNum(10)  // 输出 "数字:10"

// 3. 多参数闭包(显式声明参数)
def add = { a, b -> println "a + b = ${a + b}" }
add(5, 3)  // 输出 "a + b = 8"

// 4. 有返回值的闭包(最后一行表达式自动返回,无需 return)
def multiply = { a, b -> a * b }
def result = multiply(4, 5)
println "乘法结果:${result}"  // 输出 "乘法结果:20"
示例 2:闭包访问外部变量(核心特性)

闭包能直接访问定义它的外部作用域变量,甚至修改(无需传参):

groovy

复制代码
// 外部变量
def base = 10

// 闭包访问并修改外部变量
def calculate = { num -> 
    base += num  // 修改外部变量
    println "base + num = ${base}"
}

calculate(5)  // base 变为 15,输出 "base + num = 15"
calculate(3)  // base 变为 18,输出 "base + num = 18"
println "最终base:${base}"  // 输出 "最终base:18"
示例 3:闭包作为方法参数(集合遍历,Jenkins 高频)

Groovy 集合(List/Map)的 each/find/collect 等方法都接受闭包作为参数,替代繁琐的循环:

groovy

复制代码
// 1. List 遍历(each 方法 + 闭包)
def list = [1, 2, 3, 4, 5]
// 简化写法:单参数用 it
list.each { println "元素:${it}" }
// 输出:
// 元素:1
// 元素:2
// ...

// 带索引遍历(eachWithIndex + 多参数闭包)
list.eachWithIndex { num, index -> 
    println "索引${index}:${num}"
}
// 输出:
// 索引0:1
// 索引1:2
// ...

// 2. 集合过滤(findAll + 闭包):筛选偶数
def evenNums = list.findAll { it % 2 == 0 }
println "偶数列表:${evenNums}"  // 输出 "偶数列表:[2, 4]"

// 3. 集合转换(collect + 闭包):所有元素翻倍
def doubleNums = list.collect { it * 2 }
println "翻倍列表:${doubleNums}"  // 输出 "翻倍列表:[2, 4, 6, 8, 10]"

// 4. Map 遍历(闭包参数为 entry,key/value 可解构)
def map = [name: "张三", age: 20, city: "北京"]
map.each { key, value -> 
    println "${key}:${value}"
}
// 输出:
// name:张三
// age:20
// city:北京
示例 4:闭包作为方法的返回值(进阶)

闭包可作为方法返回值,实现 "动态生成逻辑":

groovy

复制代码
// 定义方法,返回一个闭包(根据输入的运算符,生成对应的计算逻辑)
def getCalculator(String operator) {
    switch (operator) {
        case "+": return { a, b -> a + b }
        case "-": return { a, b -> a - b }
        case "*": return { a, b -> a * b }
        default: return { a, b -> 0 }
    }
}

// 获取加法闭包并执行
def add = getCalculator("+")
println "5 + 3 = ${add(5, 3)}"  // 输出 "5 + 3 = 8"

// 获取乘法闭包并执行
def multiply = getCalculator("*")
println "4 * 6 = ${multiply(4, 6)}"  // 输出 "4 * 6 = 24"
示例 5:闭包的默认参数和自定义参数名(避免 it 歧义)

当闭包逻辑复杂时,建议显式声明参数名,替代默认的 it,提升可读性:

groovy

复制代码
// 反例:嵌套闭包用 it 导致歧义
def list = [[name: "张三", age:20], [name: "李四", age:25]]
// list.each { it.each { println it } }  // 内层 it 指代什么?可读性差

// 正例:显式声明参数名
list.each { user ->  // 外层参数名:user
    user.each { key, value ->  // 内层参数名:key/value
        println "用户${user.name}的${key}:${value}"
    }
}
// 输出:
// 用户张三的name:张三
// 用户张三的age:20
// 用户李四的name:李四
// 用户李四的age:25
示例 6:Jenkins 流水线中的闭包(实战核心)

Jenkins Pipeline 本质是 Groovy 脚本,闭包是流水线的核心语法(如 pipeline {}/stage {}/steps {} 都是闭包):

groovy

复制代码
pipeline {  // 最外层闭包
    agent any
    stages {  // 嵌套闭包
        stage('构建') {  // 嵌套闭包
            steps {  // 嵌套闭包
                script {
                    // 流水线中使用闭包遍历分支
                    def branches = ["master", "dev", "test"]
                    branches.each { branch ->  // 业务逻辑闭包
                        echo "开始构建分支:${branch}"
                        git url: 'https://git.example.com/project.git', branch: branch
                        sh "mvn clean package"
                    }
                }
            }
        }
    }
}

三、闭包的关键总结

  1. 核心本质:闭包是可执行的代码块对象,支持参数、返回值,能访问外部变量;
  2. 简化语法 :单参数闭包可省略参数声明,用 it 指代参数;
  3. 高频场景:集合遍历 / 过滤 / 转换、Jenkins 流水线、动态生成业务逻辑;
  4. 可读性原则 :简单逻辑用 it,复杂逻辑 / 嵌套闭包显式声明参数名。

如果需要针对 Jenkins 流水线场景的闭包实战(如动态生成 stage、根据参数执行不同逻辑),我可以补充更贴合工作的示例。

相关推荐
_Soy_Milk2 小时前
【算法工程师】—— Python 高级
开发语言·python·算法
2401_861412142 小时前
python 从入门到精通 高清PDF 背记手册
开发语言·python·pdf
幻云20102 小时前
Python机器学习:筑基与实践
前端·人工智能·python
喵手2 小时前
Python爬虫零基础入门【第二章:网页基础·第2节】你要抓的到底是什么:HTML、CSS 选择器、XPath 入门?
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·网页基础·网页结构解析
lsx2024062 小时前
jEasyUI 条件设置行背景颜色
开发语言
飞天小蜈蚣2 小时前
python-django_ORM的十三个查询API接口
开发语言·python·django
飞雪20072 小时前
局域网服务发现技术, DNS-SD和mDNS具体有什么区别, 什么不同?
开发语言·局域网·mdns·airplay·dns-sd·airprint
人工智能AI技术2 小时前
【Agent从入门到实践】18 脚本化编程:批量执行、自动化逻辑
人工智能·python
开开心心就好2 小时前
打印机驱动搜索下载工具,自动识别手动搜
java·linux·开发语言·网络·stm32·物联网·电脑