CodeGym /课程 /JAVA 25 SELF /枚举:enum

枚举:enum

JAVA 25 SELF
第 10 级, 课程 4
可用

1. 引言

在编程中,我们经常需要操作一组预先已知且有限的选项。例如:一周中的天数、红绿灯的颜色、游戏难度级别、订单状态。每个选项通常由一个固定的值表示。由此我们就引出了今天的主题——枚举(enum)。

枚举是一种特殊的数据类型,用于声明一组具名常量。

enum就像一个把标签分好格子的盒子,每个标签都是与数字关联的唯一名称。

enum 的主要优点:

  • 你的代码将变得更易读且更自文档化;
  • 不再充斥神秘的“魔法数字”,如 0、1、2,而是有表达力的名字:DayOfWeek.MONDAY 或 TrafficLight.RED;
  • 如果你尝试赋予非法值,编译器会报错;
  • 每个元素背后其实都对应一个普通的整数!(后面我们还会提到。)

enum 的声明语法


// 枚举声明的通用模板
public enum Name
{
    CONSTANT1 ,
    CONSTANT2 ,
    CONSTANT3
}
enum 的声明语法

在 Java 中声明枚举非常简单。下面是一个基础示例:

// 文件 DayOfWeek.java
public enum DayOfWeek {
    MONDAY,			// 0	
    TUESDAY,		// 1
    WEDNESDAY,		// 2
    THURSDAY,		// 3
    FRIDAY,			// 4
    SATURDAY,		// 5
    SUNDAY			// 6
}

说明:

  • 关键字 enum 告诉编译器:“这是一个枚举!”
  • 在花括号内用逗号分隔列出各个选项(常量)。
  • 通常使用 UPPER_SNAKE_CASE 命名(全大写,单词间用下划线)。

在哪里可以声明 enum?

  • 在单独的文件中(DayOfWeek.java)。
  • 在类内部(如果只想让该类私用一个私有枚举)。
  • 甚至在方法内部(不过较少这样做)。

2. 在代码中使用 enum

声明一个 enum 变量:

DayOfWeek today = DayOfWeek.MONDAY;

现在,today 只能取 DayOfWeek 中声明的那些值之一。

在 switch 中的使用示例

switch (today) 
{
    case MONDAY:
        System.out.println("唉,星期一……");
        break;
    case FRIDAY:
        System.out.println("万岁,星期五!");
        break;
    default:
        System.out.println("普通的一天。");
}

重要区别:在 case 中直接写常量名(不加前缀),前提是编译器已经知道变量的类型。

遍历 enum 的所有值

每个枚举都有一个静态方法 values(),它返回包含其所有值的数组:

for (DayOfWeek day : DayOfWeek.values()) 
{
    System.out.println(day);
}

这对于输出菜单、校验、生成选项等非常方便。

3. enum 的方法:name()、ordinal()、valueOf()

Java 中的枚举不仅仅是常量列表,它们还是带有方法的完整类!

name() 方法

返回常量在代码中的名字(字符串,大小写与声明一致):

DayOfWeek day = DayOfWeek.FRIDAY;
System.out.println(day.name()); // "FRIDAY"

ordinal() 方法

返回常量的序号(从 0 开始):

System.out.println(DayOfWeek.MONDAY.ordinal()); // 0
System.out.println(DayOfWeek.FRIDAY.ordinal()); // 4

注意:如果将来顺序可能变化,不要用 ordinal() 来存储或比较枚举!更好的做法是使用名称。

valueOf(String name) 方法

将字符串转换为对应的枚举值(如果该常量存在):

DayOfWeek day = DayOfWeek.valueOf("MONDAY");
System.out.println(day); // MONDAY

如果字符串不匹配——会抛出 IllegalArgumentException 异常。

values() 方法

返回该枚举的所有值数组(上面已有示例):

DayOfWeek[] days = DayOfWeek.values();

4. 带字段、构造器和方法的枚举

Java 中的枚举可以扩展:添加字段、构造器、方法!没错,它不仅是名字列表,更是一个迷你类。

示例:带本地化名称的星期

public enum DayOfWeek 
{
    MONDAY("星期一"),
    TUESDAY("星期二"),
    WEDNESDAY("星期三"),
    THURSDAY("星期四"),
    FRIDAY("星期五"),
    SATURDAY("星期六"),
    SUNDAY("星期日");

    private final String russianName;

    // 构造器(默认是 private)
    DayOfWeek(String russianName) 
    {
        this.russianName = russianName;
    }

    public String getRussianName() 
    {
        return russianName;
    }
}

关于其工作原理的更多细节,我们会在 27+ 级开始学习 OOP 时讲到 :P

现在可以这样用:

DayOfWeek day = DayOfWeek.WEDNESDAY;
System.out.println(day.getRussianName()); // "星期三"

小技巧:每个枚举值都可以有自己的数据(本例中是名为 russianName 的“俄语名称”字段)。

使用 enum 的优势

  • 类型安全:无法把列表之外的值意外赋给枚举变量。
  • 可读性:代码自带文档(TrafficLight.RED 替代 1 或 "red")。
  • 维护方便:需要新增或删除选项时,只需在一个地方修改。
  • 可与 switch 配合:enum 非常适合按值分支。
  • 可扩展:可以添加字段、方法,实现接口。
  • 更少错误:编译器会帮助你不要漏掉分支(尤其是在 switch 结构中)。

6. 实战:在我们的应用中使用 enum

让我们在这个迷你应用中通过 enum 添加对星期的支持。

步骤 1. 声明枚举

public enum DayOfWeek 
{
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

步骤 2. 在代码中使用

System.out.println("请输入星期(例如,MONDAY):"); 
Scanner console = new Scanner(System.in);                      
String input = console.nextLine().toUpperCase();               
                                                               
DayOfWeek day = DayOfWeek.valueOf(input);                      
switch (day) 
{                                                 
    case MONDAY:                                               
        System.out.println("工作周开始了!");          
        break;                                                 
    case FRIDAY:                                               
        System.out.println("周末就要到了!");                 
        break;                                                 
    case SATURDAY:                                             
    case SUNDAY:                                               
        System.out.println("太好了,周末!");                  
        break;                                                 
    default:                                                   
        System.out.println("普通的工作日。");           
}                                                              

发生了什么:

  • 用户输入星期(例如,"monday" 或 "MONDAY")。
  • 将字符串转为大写(toUpperCase()),以避免大小写差异的影响。
  • 通过 valueOf 将字符串转换为枚举值。
  • 使用 switch 输出不同的消息。
  • 如果输入不正确——捕获错误并给出警告。

7. 使用 enum 的常见错误

错误 №1:用字符串或数字代替 enum。 初学者常常还会这样写:

int day = 1; // 1 是星期一吗?

或者

String status = "DELIVERED";

这样不好:容易拼写出错,代码难以维护。请使用 enum!

错误 №2:用 == 与 .equals() 比较枚举。 在 Java 中可以用 == 比较 enum 的值——这是安全的,因为在同一个枚举类中每个值都是唯一的:

if (day == DayOfWeek.MONDAY) { ... } // OK!

尽管 .equals() 也能用,但更常见的是 ==。

错误 №3:糟糕的枚举命名。 不要把元素命名成 VALUE1、VALUE2、VALUE3——过一个月谁也看不懂!请使用有意义的名称。

错误 №4:在逻辑中使用 ordinal()。 不要这样写:

if (day.ordinal() == 0) { ... } // 别这样!

元素顺序可能会改变,逻辑就会崩。请使用名称!

1
任务
JAVA 25 SELF, 第 10 级, 课程 4
已锁定
交通信号灯建模 🚦
交通信号灯建模 🚦
1
任务
JAVA 25 SELF, 第 10 级, 课程 4
已锁定
应用中的季节性祝福 🌸☀️🍁❄️
应用中的季节性祝福 🌸☀️🍁❄️
1
任务
JAVA 25 SELF, 第 10 级, 课程 4
已锁定
应用中的周计划 🗓️
应用中的周计划 🗓️
1
任务
JAVA 25 SELF, 第 10 级, 课程 4
已锁定
太空旅行导航 🚀
太空旅行导航 🚀
评论 (1)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
悠 级别 1,-,Hong Kong
25 七月 2026
春天——万物复苏!夏天——度假的时光!秋天——丰收的季节!冬天——滑雪的季节!