跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Java 枚举(Enum)详解

系统讲解 Java 枚举类型,包括基本语法、带属性与方法的高级用法、内置实用方法及集合类。深入探讨枚举在单例、策略及状态模式中的应用,对比枚举与常量的优劣,强调类型安全与序列化优势。最后分析枚举的局限性并提供 HTTP 状态码与配置管理的实战案例,帮助开发者提升代码质量与维护性。

樱花落尽发布于 2026/3/30更新于 2026/10/22119 浏览
Java 枚举(Enum)详解

1. 枚举的基本概念

1.1 为什么需要枚举?

在枚举出现之前,我们通常使用常量来表示固定值:

// 旧的方式:使用常量
public class OldStyle {
    public static final int MONDAY = 1;
    public static final int TUESDAY = 2;
    public static final int WEDNESDAY = 3;
    // ... 其他天
    public void setDay(int day) {
        // 可能传入非法值,如 100
    }
}

这种方式的问题:

  • 类型不安全
  • 没有命名空间
  • 可读性差
  • 无法添加行为

1.2 枚举的基本语法

// 简单的枚举定义
public enum Day {
    MONDAY, // 枚举常量
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

2. 枚举的高级特性

2.1 带属性的枚举

枚举可以拥有字段、构造方法和普通方法:

public 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;   // 质量(千克)
    private final double radius; // 半径(米)

    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }

    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }

    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }

    public static final double G = 6.67300E-11;
}

2.2 枚举的方法

枚举可以定义抽象方法和具体方法:

public enum Operation {
    PLUS {
        public double apply(double x, double y) {
            return x + y;
        }
    },
    MINUS {
        public double apply(double x, double y) {
            return x - y;
        }
    },
    TIMES {
        public double apply(double x, double y) {
            return x * y;
        }
    },
    DIVIDE {
        public double apply(double x, double y) {
            return x / y;
        }
    };

    public abstract double apply(double x, double y);
}

2.3 枚举实现接口

枚举可以实现接口,提供多态行为:

public interface Command {
    void execute();
}

public enum FileOperation implements Command {
    OPEN {
        public void execute() {
            System.out.println("打开文件");
        }
    },
    SAVE {
        public void execute() {
            System.out.println("保存文件");
        }
    },
    CLOSE {
        public void execute() {
            System.out.println("关闭文件");
        }
    };

    public abstract void execute();
}

3. 枚举的实用方法

3.1 内置方法

public class EnumMethods {
    public static void main(String[] args) {
        // 获取所有枚举值
        Day[] days = Day.values();
        for (Day day : days) {
            System.out.println(day);
        }

        // 根据名称获取枚举
        Day monday = Day.valueOf("MONDAY");
        System.out.println(monday); // 输出:MONDAY

        // 获取枚举名称和序号
        System.out.println(monday.name());      // 输出:MONDAY
        System.out.println(monday.ordinal());   // 输出:0(序号)

        // 比较枚举
        Day tuesday = Day.TUESDAY;
        System.out.println(monday.compareTo(tuesday)); // 输出:-1
    }
}

3.2 枚举集合

Java 提供了专门的枚举集合类:

public class EnumCollections {
    public static void main(String[] args) {
        // EnumSet - 高效的枚举集合
        EnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
        EnumSet<Day> weekdays = EnumSet.range(Day.MONDAY, Day.FRIDAY);
        EnumSet<Day> allDays = EnumSet.allOf(Day.class);

        // EnumMap - 键为枚举的 Map
        EnumMap<Day, String> activities = new EnumMap<>(Day.class);
        activities.put(Day.MONDAY, "开会");
        activities.put(Day.FRIDAY, "团队建设");
        System.out.println(activities.get(Day.MONDAY)); // 输出:开会
    }
}

4. 枚举的设计模式应用

4.1 单例模式

枚举是实现单例的最佳方式:

public enum Singleton {
    INSTANCE;

    private int value;

    public void setValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void doSomething() {
        System.out.println("单例操作:" + value);
    }
}

// 使用
Singleton.INSTANCE.setValue(42);
Singleton.INSTANCE.doSomething();

4.2 策略模式

public enum Calculator {
    ADD {
        public int calculate(int a, int b) {
            return a + b;
        }
    },
    SUBTRACT {
        public int calculate(int a, int b) {
            return a - b;
        }
    },
    MULTIPLY {
        public int calculate(int a, int b) {
            return a * b;
        }
    },
    DIVIDE {
        public int calculate(int a, int b) {
            if (b == 0) throw new ArithmeticException("除数不能为 0");
            return a / b;
        }
    };

    public abstract int calculate(int a, int b);
}

// 使用
int result = Calculator.ADD.calculate(10, 5); // 15

4.3 状态模式

public enum OrderStatus {
    NEW {
        public OrderStatus next() {
            return CONFIRMED;
        }
    },
    CONFIRMED {
        public OrderStatus next() {
            return SHIPPED;
        }
    },
    SHIPPED {
        public OrderStatus next() {
            return DELIVERED;
        }
    },
    DELIVERED {
        public OrderStatus next() {
            return this; // 最终状态
        }
    };

    public abstract OrderStatus next();
}

// 使用
OrderStatus status = OrderStatus.NEW;
status = status.next(); // CONFIRMED

5. 枚举的最佳实践

5.1 使用枚举代替常量

// 不好的做法
public class Constants {
    public static final int RED = 1;
    public static final int GREEN = 2;
    public static final int BLUE = 3;
}

// 好的做法
public enum Color {
    RED, GREEN, BLUE
}

5.2 使用枚举保证类型安全

public class TypeSafety {
    // 旧方法 - 不安全
    public void process(int status) {
        // 可能传入非法值
    }

    // 新方法 - 安全
    public void process(Status status) {
        // 只能传入有效的枚举值
    }
}

public enum Status {
    ACTIVE, INACTIVE, PENDING
}

5.3 枚举的序列化

枚举的序列化是安全的,不需要担心单例破坏:

public enum SafeSerializable implements Serializable {
    INSTANCE;

    private int data;

    public void setData(int data) {
        this.data = data;
    }

    // 序列化安全,不需要 readResolve 方法
}

6. 枚举的局限性

6.1 不能继承

枚举不能继承其他类(已经隐式继承 Enum),但可以实现接口。

6.2 实例数量固定

枚举实例在编译时确定,运行时不能创建新的枚举实例。

6.3 内存考虑

大量枚举可能会占用较多内存,但在大多数情况下这不是问题。

7. 实际应用示例

7.1 HTTP 状态码

public enum HttpStatus {
    OK(200, "OK"),
    CREATED(201, "Created"),
    BAD_REQUEST(400, "Bad Request"),
    UNAUTHORIZED(401, "Unauthorized"),
    NOT_FOUND(404, "Not Found"),
    INTERNAL_SERVER_ERROR(500, "Internal Server Error");

    private final int code;
    private final String message;

    HttpStatus(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public static HttpStatus fromCode(int code) {
        for (HttpStatus status : values()) {
            if (status.code == code) {
                return status;
            }
        }
        throw new IllegalArgumentException("无效的状态码:" + code);
    }

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

    public boolean isError() {
        return code >= 400;
    }
}

7.2 配置管理

public enum AppConfig {
    DATABASE_URL("db.url", "jdbc:mysql://localhost:3306/mydb"),
    DATABASE_USERNAME("db.username", "root"),
    DATABASE_PASSWORD("db.password", "password"),
    MAX_CONNECTIONS("db.max.connections", "10"),
    CACHE_ENABLED("cache.enabled", "true");

    private final String key;
    private final String defaultValue;

    AppConfig(String key, String defaultValue) {
        this.key = key;
        this.defaultValue = defaultValue;
    }

    public String getKey() {
        return key;
    }

    public String getDefaultValue() {
        return defaultValue;
    }

    public String getValue() {
        return System.getProperty(key, defaultValue);
    }

    public int getIntValue() {
        return Integer.parseInt(getValue());
    }

    public boolean getBooleanValue() {
        return Boolean.parseBoolean(getValue());
    }
}

8. 总结

枚举的优势:
  1. 类型安全:编译时检查,避免非法值
  2. 可读性强:有意义的名称代替魔法数字
  3. 功能丰富:可以拥有字段、方法、实现接口
  4. 线程安全:枚举实例天生是线程安全的
  5. 序列化安全:内置的序列化机制保证安全
  6. 单例支持:是实现单例模式的最佳方式

枚举是 Java 语言中一个强大而灵活的特性,正确使用枚举可以大大提高代码的质量和可维护性。

目录

  1. 1. 枚举的基本概念
  2. 1.1 为什么需要枚举?
  3. 1.2 枚举的基本语法
  4. 2. 枚举的高级特性
  5. 2.1 带属性的枚举
  6. 2.2 枚举的方法
  7. 2.3 枚举实现接口
  8. 3. 枚举的实用方法
  9. 3.1 内置方法
  10. 3.2 枚举集合
  11. 4. 枚举的设计模式应用
  12. 4.1 单例模式
  13. 4.2 策略模式
  14. 4.3 状态模式
  15. 5. 枚举的最佳实践
  16. 5.1 使用枚举代替常量
  17. 5.2 使用枚举保证类型安全
  18. 5.3 枚举的序列化
  19. 6. 枚举的局限性
  20. 6.1 不能继承
  21. 6.2 实例数量固定
  22. 6.3 内存考虑
  23. 7. 实际应用示例
  24. 7.1 HTTP 状态码
  25. 7.2 配置管理
  26. 8. 总结
  27. 枚举的优势:

更多推荐文章

查看全部
  • 通义万相 2.1 的架构、能力与落地观察
  • C++ 二叉搜索树
  • 一卡通核心交易平台国产数据库实践:架构、迁移与高可用落地
  • OpenClaw 跨平台安装指南:Windows 与 Ubuntu
  • Python 开源聊天机器人在电商外贸智能客服中的实战应用与架构解析
  • Linux 系统下 Vim 编辑器基础操作指南
  • VS Code 远程开发 GitHub Copilot 失效排查指南
  • 滑动窗口算法详解:水果成篮问题解法
  • LeetCode 子集问题:Java 位运算与回溯法解析
  • Whisper v0.2 语音转文字工具安装与使用指南
  • BILIVE 部署与运行常见问题排查指南
  • Java 中 Integer 对象比较陷阱解析
  • C++ 多线程同步:互斥锁 mutex 实战指南
  • AI 产品经理转型指南:核心能力与实战框架
  • 基于 HDFS 的 Web 云盘管理系统
  • AI 产品经理核心专业术语解析
  • RAG 系统实现指南:Langchain 与纯手搓方案对比
  • SpringBoot 中药材进存销管理系统设计与实现
  • 飞算 JavaAI 专业版实测:全栈代码生成与开发效率提升
  • 力扣面试题解析:哈希表与双指针算法

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online