Groovy 枚举
最后修改于 2025 年 3 月 20 日
Groovy 中的枚举定义了一组固定的常量,提高了代码的可读性和类型安全性。它们建立在 Java 的枚举基础上,但支持额外的功能,如自定义方法和 Groovy 特有的语法。本教程将通过示例探索枚举的基础知识和高级用法。
简单枚举
枚举使用 enum
关键字创建,以简洁、类型安全的方式列出常量,非常适合预定义的类别。
enum Color { RED, GREEN, BLUE } println Color.RED
Color
定义了三个常量。Color.RED
直接访问其中一个,打印 "RED"。枚举是隐式的静态 final,确保这些值在程序中保持不变。
带变量的枚举
枚举可以包含实例变量,通过构造函数初始化,为每个常量添加名称以外的数据。
enum Direction { NORTH(0), EAST(90), SOUTH(180), WEST(270) int degrees Direction(int deg) { degrees = deg } } println Direction.NORTH.degrees println Direction.WEST.degrees
Direction
将每个常量与角度配对。degrees
通过构造函数设置,因此 Direction.NORTH.degrees
为 0,WEST.degrees
为 270。这表明枚举可以封装相关数据。
序数和值
枚举提供了内置方法,如用于位置的 ordinal
和用于所有常量的 values
,这些方法对于迭代和索引很有用。
enum Size { SMALL, MEDIUM, LARGE } println Size.SMALL Size.each { println it } Size.each { println "${it} ${it.ordinal()}" } println Size.values()
Size.SMALL
打印 "SMALL",这是第一个常量。each
遍历所有大小,首先列出它们,然后使用 ordinal
显示它们的零基位置(SMALL: 0, MEDIUM: 1, LARGE: 2)。values
返回一个包含所有常量的数组,方便批量访问或转换为其他集合。
字符串强制转换
Groovy 允许隐式或显式地将字符串转换为枚举值,利用其灵活的类型系统简化枚举处理。
enum State { up, down } println State.up == 'up' as State println State.down == 'down' as State State s1 = 'up' State s2 = 'down' println State.up == s1 println State.down == s2
'up' as State
将 "up" 显式强制转换为 State.up
,两个比较都返回 true。将 'up'
赋值给 s1
会隐式转换它,使其与 State.up
匹配。此功能简化了将字符串解析为枚举的过程,但大小写必须与枚举名称完全匹配。
自定义方法
枚举可以定义自定义方法,静态或实例方法,将其功能扩展到简单的常量之外,包含逻辑。
import java.util.Random def season = Season.randomSeason() String msg = switch (season) { case Season.SPRING -> "Spring" case Season.SUMMER -> "Summer" case Season.AUTUMN -> "Autumn" case Season.WINTER -> "Winter" } println(msg) enum Season { SPRING, SUMMER, AUTUMN, WINTER; static Season randomSeason() { def random = new Random() int ridx = random.nextInt(Season.values().length) Season.values()[ridx] } }
randomSeason
是一个静态方法,它使用 values
和随机索引返回一个随机的 Season
常量。switch
表达式将结果映射到友好的字符串。输出各不相同(例如,“Autumn”),显示了枚举如何封装行为,此处模拟了一个随机季节选择器。
Switch 表达式范围
枚举与 Groovy 的 switch 表达式无缝配合,包括范围和多个 case,使其在控制流中非常强大。
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') } }
Day
列出了工作日。isWeekend
使用 switch 语句,对于工作日(Monday..Friday)使用范围(返回 false),对于周末使用逗号分隔列表(Saturday, Sunday,返回 true)。循环测试所有日期,打印五次“weekday”和两次“weekend”。这展示了 Groovy 在枚举中富有表现力的范围语法。
行星
枚举可以模拟具有属性和方法的复杂对象,例如具有质量和半径的行星,展示了它们的面向对象潜力。
double earthWeight = 63 double mass = earthWeight / Planet.EARTH.surfaceGravity() for (Planet p : Planet.values()) { println("Your weight on ${p} is ${p.surfaceWeight(mass)}") } enum Planet { MERCURY (3.303e+23, 2.4397e6), VENUS (4.869e+24, 6.0518e6), EARTH (5.976e+24, 6.37814e6), MARS (6.421e+23, 3.3972e6), JUPITER (1.9e+27, 7.1492e7), SATURN (5.688e+26, 6.0268e7), URANUS (8.686e+25, 2.5559e7), NEPTUNE (1.024e+26, 2.4746e7); private final double mass // in kilograms private final double radius // in meters Planet(double mass, double radius) { this.mass = mass this.radius = radius } private double mass() { return mass } private double radius() { return radius } // universal gravitational constant (m3 kg-1 s-2) final double G = 6.67300E-11 double surfaceGravity() { return G * mass / (radius * radius) } double surfaceWeight(double otherMass) { return otherMass * surfaceGravity() } String toString() { name().toLowerCase().capitalize() } }
Planet
通过构造函数定义了八颗行星及其质量和半径。surfaceGravity
使用引力常数计算重力,surfaceWeight
计算重量。toString
格式化名称(例如,“Earth”)。循环计算一个 63kg 在地球上的体重,并将其转换为在其他行星上的体重,展示了枚举作为具有实际应用的全功能对象。
集合中的枚举
枚举可以用于列表等集合中,利用其常量性质进行迭代或数据存储。
enum Fruit { APPLE, BANANA, ORANGE } def fruits = [Fruit.APPLE, Fruit.BANANA, Fruit.ORANGE] fruits.each { println it }
Fruit
定义了三个常量。存储在列表中,fruits.each
遍历它们,打印每个名称。这说明了枚举如何与 Groovy 的集合功能集成,在保持类型安全的同时可迭代。
来源
本教程通过实际示例探讨了 Groovy 枚举。
作者
列出 所有 Groovy 教程。