0Pricing
Java Academy · 课时

定义和使用枚举

声明枚举类型,使用其中的常量,并通过 values() 和 ordinal() 进行遍历

定义和使用枚举 是 CoddyKit 上的免费 Java Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

定义和使用枚举

枚举是一种表示固定常量集合的特殊类。枚举具有类型安全、可读性强等优点,也比静态 int 常量更强大。

声明枚举

使用 enum 关键字声明枚举。每个常量都会隐式成为 public static final,并且是该枚举类型的一个实例。

enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
    FRIDAY, SATURDAY, SUNDAY
}

Day today = Day.WEDNESDAY;
System.out.println(today);          // WEDNESDAY
System.out.println(today.name());   // WEDNESDAY
System.out.println(today.ordinal()); // 2 (zero-based index)

使用 values() 迭代

EnumType.values() 按声明顺序返回所有常量。请使用它进行迭代或构建菜单。

enum Planet { MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE }

for (Planet p : Planet.values()) {
    System.out.println(p.ordinal() + ": " + p);
}
// 0: MERCURY
// 1: VENUS
// 2: EARTH
// ...

// Count constants
System.out.println(Planet.values().length); // 8

valueOf() 与解析

Enum.valueOf(name) 会将 String 转换为匹配的常量。如果找不到匹配项,则抛出 IllegalArgumentException。

enum Status { PENDING, ACTIVE, SUSPENDED, CLOSED }

String input = "ACTIVE";
Status s = Status.valueOf(input);
System.out.println(s); // ACTIVE

try {
    Status bad = Status.valueOf("UNKNOWN");
} catch (IllegalArgumentException e) {
    System.out.println("Invalid status: UNKNOWN");
}

// Safe parse pattern
static Status safeFrom(String name) {
    try { return Status.valueOf(name.toUpperCase()); }
    catch (IllegalArgumentException e) { return Status.PENDING; }
}

在 switch 中使用枚举

枚举可以完美地用于 switch 语句和表达式。现代 switch 表达式可以简洁且完整地处理枚举分支。

enum OrderStatus { CREATED, PROCESSING, SHIPPED, DELIVERED, CANCELLED }

OrderStatus status = OrderStatus.SHIPPED;

String message = switch (status) {
    case CREATED     -> "Order received, awaiting payment";
    case PROCESSING  -> "Payment confirmed, preparing shipment";
    case SHIPPED     -> "On the way — track your package";
    case DELIVERED   -> "Delivered! Enjoy your order";
    case CANCELLED   -> "Order cancelled";
};
System.out.println(message); // On the way — track your package

使用 if/else 处理枚举

请使用 == 比较枚举常量:它们是单例实例,因此引用相等性可以正常工作。

enum UserRole { GUEST, MEMBER, ADMIN, SUPERADMIN }

UserRole role = UserRole.ADMIN;

if (role == UserRole.ADMIN || role == UserRole.SUPERADMIN) {
    System.out.println("Access granted to admin panel");
} else {
    System.out.println("Access denied");
}

// Enum comparison: never use .equals() for enums
// == is correct and more readable

在集合中使用枚举

枚举可以存储在标准集合中。请使用 EnumSet 和 EnumMap 进行高性能的基于枚举的存储(将在后续课程中介绍)。

import java.util.*;

enum Permission { READ, WRITE, DELETE, ADMIN }

Set<Permission> userPerms = new HashSet<>();
userPerms.add(Permission.READ);
userPerms.add(Permission.WRITE);

System.out.println(userPerms.contains(Permission.DELETE)); // false
System.out.println(userPerms.contains(Permission.READ));   // true

List<Permission> allPerms = Arrays.asList(Permission.values());
System.out.println(allPerms.size()); // 4

枚举实现接口

枚举可以实现接口,从而能够为每个常量附加行为,或为所有常量定义通用契约。

interface Describable {
    String describe();
}

enum Season implements Describable {
    SPRING, SUMMER, FALL, WINTER;

    public String describe() {
        return switch (this) {
            case SPRING -> "Mild and rainy";
            case SUMMER -> "Hot and sunny";
            case FALL   -> "Cool with falling leaves";
            case WINTER -> "Cold and snowy";
        };
    }
}

for (Season s : Season.values()) {
    System.out.println(s + ": " + s.describe());
}

将枚举用作状态机

枚举非常适合状态机。每个常量表示一种状态,而方法定义有效的状态转换。

enum TrafficLight {
    RED, YELLOW, GREEN;

    public TrafficLight next() {
        return switch (this) {
            case RED    -> GREEN;
            case GREEN  -> YELLOW;
            case YELLOW -> RED;
        };
    }
}

TrafficLight light = TrafficLight.RED;
for (int i = 0; i < 6; i++) {
    System.out.println(light);
    light = light.next();
}
// RED, GREEN, YELLOW, RED, GREEN, YELLOW

枚举最佳实践

使用枚举时请遵循以下最佳实践:

  • 为常量使用全大写名称(约定)
  • 为了类型安全,优先使用枚举,而不是 int 或 String 常量
  • 使用 switch 表达式完整地处理所有分支
  • 当常量携带数据时,为枚举添加字段和方法

实践:HTTP 状态码

一个真实场景中的枚举示例:使用工厂方法根据数字代码创建 HTTP 状态类别。

enum HttpStatus {
    OK(200), CREATED(201), BAD_REQUEST(400),
    UNAUTHORIZED(401), NOT_FOUND(404), SERVER_ERROR(500);

    public final int code;

    HttpStatus(int code) { this.code = code; }

    public static HttpStatus from(int code) {
        for (HttpStatus s : values())
            if (s.code == code) return s;
        throw new IllegalArgumentException("Unknown HTTP code: " + code);
    }

    public boolean isSuccess() { return code >= 200 && code < 300; }
}

HttpStatus s = HttpStatus.from(404);
System.out.println(s + " (" + s.code + ") success=" + s.isSuccess());
// NOT_FOUND (404) success=false

快速检查

下面代码的输出是什么?

enum Color { RED, GREEN, BLUE }
System.out.println(Color.GREEN.ordinal());

总结:定义和使用枚举

要点:

  • 枚举定义一组固定的命名常量,并提供类型安全
  • values() 迭代所有常量;ordinal() 返回从零开始的索引
  • valueOf() 将 String 转换为匹配的常量
  • 使用 ==(而不是 equals)比较枚举实例
  • 枚举非常适合用于 switch 表达式,以完整地处理所有分支
  • 枚举可以实现接口,为每个常量附加行为

常见问题解答

「定义和使用枚举」课时是免费的吗?

是的 — 「定义和使用枚举」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「定义和使用枚举」这节课中我会学到什么?

声明枚举类型,使用其中的常量,并通过 values() 和 ordinal() 进行遍历 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「定义和使用枚举」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 定义和使用枚举
  2. 带字段和方法的枚举
  3. 使用枚举的 switch 表达式
  4. EnumSet 与 EnumMap
← 返回 Java Academy