Groovy Switch 表达式
最后修改于 2025 年 3 月 20 日
Groovy 中的 Switch 表达式,也称为模式匹配,提供了一种处理多个条件的简洁方式。与传统 switch 不同,它们返回一个值,增强了表达力。本教程通过示例探讨了它们的通用性。
简单 Switch
Switch 表达式使用 `->` 语法根据条件返回值,简化了基本的决策制定。
def num = 3
def res = switch (num) {
case 3 -> "three"
default -> "other"
}
println res
switch (num) 检查 num (3) 与 case。case 3 匹配,返回 "three"。default case 处理不匹配的值。这种紧凑的形式直接返回值,不像基于语句的 switch。
$ groovy SimpleSwitch.groovy three
匹配字符串字面量
Switch 表达式可以匹配字符串输入,使其成为基于文本的条件的理想选择,例如用户响应。
def res = System.console().readLine 'Capital of Slovakia?: '
def capital = res.capitalize()
def msg = switch (capital) {
case 'Bratislava' -> 'correct answer'
default -> 'wrong answer'
}
println msg
readLine 获取用户输入,并将其大写以保持一致。switch (capital) 检查是否为 "Bratislava",返回 "correct answer",否则通过 default 返回 "wrong answer"。这展示了带回退机制的字符串匹配,对于测验或验证很有用。
$ groovy SwitchStrings.groovy Capital of Slovakia?: bratislava correct answer
匹配整数
整数匹配允许 switch 表达式处理数字选项,这在菜单驱动的程序中很常见。
def menu = '''
Select option
1 - start
2 - slow down
3 - accelerate
4 - pause
5 - terminate
'''
println menu
def opt = System.console().readLine ': '
def res = switch (opt as Integer) {
case 1 -> 'start'
case 2 -> 'slow down'
case 3 -> 'accelerate'
case 4 -> 'pause'
case 5 -> 'terminate'
default -> 'unknown'
}
println "your option: $res"
显示菜单,然后 opt as Integer 将输入转换为数字。switch 将 1-5 映射到操作,default 用于无效输入。这将返回一个字符串,如 "your option: accelerate",演示了数字模式匹配。
$ groovy SwitchIntegers.groovy Select option 1 - start 2 - slow down 3 - accelerate 4 - pause 5 - terminate : 3 your option: accelerate
匹配类型
Switch 表达式可以匹配对象类型,在混合集合中识别值的类。
def data = [1, 2.2, 'falcon', true, [1, 2, 3], 2g]
for (e in data) {
def res = switch (e) {
case Integer -> 'integer'
case String -> 'string'
case Boolean -> 'boolean'
case List -> 'list'
default -> 'other'
}
println res
}
data 包含各种类型。switch (e) 检查每个元素的类型,返回一个标签(例如,1 为 "integer",[1, 2, 3] 为 "list")。default 捕获 BigDecimal (2g)。这突显了用于动态数据的基于类型的模式匹配。
$ groovy SwitchTypes.groovy integer other string boolean list other
多个选项
逗号分隔的 case 将多个值分组到一个结果下,从而简化了具有共享结果的条件。
def grades = ['A', 'B', 'C', 'D', 'E', 'F', 'FX']
for (grade in grades) {
switch (grade) {
case 'A' , 'B' , 'C' , 'D' , 'E' , 'F' -> println('passed')
case 'FX' -> println('failed')
}
}
grades 列出了成绩。case 'A' , 'B' , ... 对及格成绩 (A-F) 进行分组,打印 "passed",而 'FX' 打印 "failed"。这种逗号语法将多个匹配合并为一个操作,提高了可读性。
$ groovy SwitchMultiple.groovy passed passed passed passed passed passed failed
默认选项
递归函数中的 default case 提供了一个通配符,演示了 switch 表达式的返回值实用性。
def factorial(n) {
switch (n) {
case 0, 1 -> 1
default -> n * factorial(n - 1)
}
}
for (i in 0g..5g) {
def f = factorial(i)
println("$i $f")
}
factorial 使用 switch 计算阶乘。case 0, 1 返回 1(基本情况),default 递归乘法。循环打印从 0 到 5 的阶乘(例如,5 120)。这表明 switch 在递归中作为表达式。
$ groovy SwitchDefault.groovy 0 1 1 1 2 2 3 6 4 24 5 120
选项内的 Guard
Guard 使用闭包为 case 添加条件,从而超越简单的相等性来细化匹配。
def rnd = new Random()
def ri = rnd.nextInt(-5, 5)
def res = switch (ri) {
case { ri < 0 } -> "${ri}: negative value"
case { ri == 0 } -> "${ri}: zero"
case { ri > 0 } -> "${ri}: positive value"
}
println res
ri 是一个随机整数(-5 到 4)。switch 使用 guard:{ ri < 0 } 用于负数,{ ri == 0 } 用于零,{ ri > 0 } 用于正数。输出各不相同(例如,“-3: negative value”),展示了动态条件匹配。
$ groovy SwitchGuards.groovy 2: positive value // varies per run
匹配枚举
Enum 与 switch 表达式自然配对,匹配特定常量以实现类型安全逻辑。
enum Day {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
def days = [Day.Monday, Day.Tuesday, Day.Wednesday, Day.Thursday,
Day.Friday, Day.Saturday, Day.Sunday]
def res = []
def random = new Random()
(0..3).each {
res << days[random.nextInt(days.size())]
}
for (e in res) {
switch (e) {
case Day.Monday -> println("monday")
case Day.Tuesday -> println("tuesday")
case Day.Wednesday -> println("wednesday")
case Day.Thursday -> println("thursday")
case Day.Friday -> println("friday")
case Day.Saturday -> println("saturday")
case Day.Sunday -> println("sunday")
}
}
Day enum 定义了工作日。选择四个随机日期,然后 switch 匹配每个日期,打印其名称(例如,“tuesday”)。输出各不相同,但这表明 enum 是 switch 的目标,利用其固定值来实现清晰度。
$ groovy SwitchEnums.groovy friday monday sunday thursday // varies per run
匹配 Enum 范围
Switch 表达式支持 enum 范围,将连续值分组以实现简洁的逻辑。
enum Day {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
def isWeekend(Day d) {
switch (d) {
case Day.Monday..Day.Friday -> false
case Day.Saturday, Day.Sunday -> true
}
}
def days = [Day.Monday, Day.Tuesday, Day.Wednesday, Day.Thursday,
Day.Friday, Day.Saturday, Day.Sunday]
for (e in days) {
if (isWeekend(e)) {
println('weekend')
} else {
println('weekday')
}
}
isWeekend 使用 Monday..Friday 用于工作日(false)和 Saturday, Sunday 用于周末(true)。循环测试所有日期,打印五次“weekday”,然后两次“weekend”。这有效地结合了范围和多个匹配。
$ groovy SwitchEnumRanges.groovy weekday weekday weekday weekday weekday weekend weekend
匹配对象
Switch 表达式可以匹配对象类型,将相关类分组以进行共享处理。
record Cat(String name) {}
record Dog(String name) {}
record Person(String name) {}
def data = [new Cat('Missy'), new Dog('Jasper'), new Dog('Ace'),
new Person('Peter'), 'Jupiter']
for (e in data) {
switch (e) {
case Cat, Dog -> println("${e} is a pet")
case Person -> println("${e} is a human")
default -> println('unknown')
}
}
Cat、Dog 和 Person 是记录。case Cat, Dog 对宠物进行分组,case Person 匹配人类,default 捕获其他(例如,“Jupiter”)。这会打印基于类型的消息,显示对象模式匹配。
$ groovy SwitchObjects.groovy Cat[name=Missy] is a pet Dog[name=Jasper] is a pet Dog[name=Ace] is a pet Person[name=Peter] is a human unknown
匹配范围
Switch 表达式中的数字范围检查一个值是否在边界内,这对于对数字进行分类很有用。
def rnd = new Random()
def ri = rnd.nextInt(0, 120)
switch (ri) {
case 1..30 -> println('value is in 1 to 30')
case 31..60 -> println('value is in 31 to 60')
case 61..90 -> println('value is in 61 to 90')
case 91..120 -> println('value is in 91 to 120')
}
ri 是随机的(0-119)。switch 检查范围(例如,1..30),打印匹配范围的消息。输出各不相同(例如,“value is in 61 to 90”),展示了范围如何有效地划分数值。
$ groovy SwitchRanges.groovy value is in 61 to 90 // varies per run
匹配正则表达式
Switch 表达式可以将字符串与正则表达式模式匹配,根据复杂标准进行过滤。
def words = ['week', 'bitcoin', 'cloud', 'copper', 'raw', 'war',
'cup', 'water']
def selected = []
for (word in words) {
def res = switch (word) {
case ~/^w.*/ -> word
case ~/^c.*/ -> word
default -> 'skip'
}
if (res != 'skip') {
selected.add(res)
}
}
println selected
~/^w.*/ 匹配以 "w" 开头的单词,~/^c.*/ 匹配以 "c" 开头的单词。返回匹配的单词,其他则为 "skip"。selected 收集匹配项(例如,“week”、“cloud”),显示了正则表达式模式匹配的实际应用。
$ groovy SwitchRegex.groovy [week, cloud, copper, war, cup, water]
匹配列表(包含)
Switch 表达式可以检查一个值是否在一个列表中,这对于数据结构中的成员资格测试很有用。
def users = [
['John', 'Doe', 'gardener'],
['Jane', 'Doe', 'teacher'],
['Roger', 'Roe', 'driver'],
['Martin', 'Molnar', 'programmer'],
['Robert', 'Kovac', 'shopkeeper'],
['Tomas', 'Novy', 'programmer']
]
def occupation = 'programmer'
for (user in users) {
switch (occupation) {
case user -> println("${user[0]} ${user[1]} is a programmer")
default -> println("${user[0]} ${user[1]} is not a programmer")
}
}
users 列出了姓名-职业对。case user 检查 "programmer" 是否在 user(列表)中,并相应地打印。这识别了程序员(Martin、Tomas),使用列表包含作为模式。
$ groovy SwitchListContains.groovy John Doe is not a programmer Jane Doe is not a programmer Roger Roe is not a programmer Martin Molnar is a programmer Robert Kovac is not a programmer Tomas Novy is a programmer
匹配列表(属性检查)
Switch 表达式可以测试列表属性,例如检查子列表中的值,从而增强数据查询。
def users = [
['name': 'Paul', 'grades': ['D', 'A', 'B', 'A']],
['name': 'Martin', 'grades': ['F', 'B', 'E', 'FX']],
['name': 'Lucia', 'grades': ['A', 'A', 'B', 'FX']],
['name': 'Jan', 'grades': ['A', 'B', 'B', 'B']]
]
for (user in users) {
switch ('FX') {
case user.grades -> println("${user.name} did not pass")
}
}
users 将姓名映射到成绩。case user.grades 检查 'FX' 是否在 grades 列表中,并为不及格者(Martin、Lucia)打印。这使用 switch 查询子列表内容,并隐式跳过不匹配项。
$ groovy SwitchListProperty.groovy Martin did not pass Lucia did not pass
来源
本教程通过示例探讨了 Groovy switch 表达式。
作者
列出 所有 Groovy 教程。