【Java】深入理解 Java 枚举(Enum)

在 Java 开发中,我们经常会遇到这样的需求:

  • 状态值:SUCCESS / FAIL
  • 订单状态:CREATED / PAID / SHIPPED / FINISHED
  • 星期:MONDAY / TUESDAY / ...

刚开始学习时,很多时候会考虑 intString 常量来表示,但这种做法类型不安全、可读性差、易出错

Java 从 JDK 1.5 开始引入了 枚举(Enum) ,用来安全、优雅地表示一组固定的常量。本文将详细介绍枚举类型,如有问题,欢迎在评论区留言( •̀ ω •́ )✧


文章目录

一、什么是枚举(Enum)

1.1 定义

枚举是一种特殊的类,用来表示一组有限、固定、可枚举的实例

java 复制代码
public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
  • 每一个枚举值都是 Day 的一个实例
  • 实例数量在编译期就已确定
  • JVM 保证每个枚举值 全局唯一(单例)

JVM会默认在每个实例对象前加public static final

问:通过enum定义的枚举类,和其他的class有什么区别?

答:答案是没有任何区别。enum定义的类型就是class


二、为什么不用 int / String 常量?

2.1 传统常量的问题

java 复制代码
public static final int SUCCESS = 1;
public static final int FAIL = 0;

❌ 问题:

  • 没有类型约束
  • IDE 无法智能提示
  • 可能传错值而编译不报错
java 复制代码
method(100); // 编译通过,运行期才发现问题

2.2 枚举的优势

优势 说明
类型安全 编译期校验
可读性强 语义明确
可扩展 可加字段和方法
天然单例 JVM 保证
switch 支持 语法友好

三、枚举的基本用法

3.1 定义与使用

java 复制代码
public enum Status {
    SUCCESS, FAIL
}
java 复制代码
Status status = Status.SUCCESS;

3.2 switch 中使用枚举

java 复制代码
switch (status) {
    case SUCCESS:
        System.out.println("成功");
        break;
    case FAIL:
        System.out.println("失败");
        break;
}

✔ 不需要写 Status.SUCCESS


四、枚举的本质:它其实是一个类

4.1 反编译后的结构(简化)

java 复制代码
public final class Status extends Enum<Status> {
    public static final Status SUCCESS = new Status("SUCCESS", 0);
    public static final Status FAIL = new Status("FAIL", 1);
}

关键点:

  • 枚举 继承自 java.lang.Enum
  • 构造器是 private
  • 实例在类加载时创建

4.2 为什么枚举不能继承类?

java 复制代码
public enum A extends B {} // ❌ 编译错误

因为:

  • Java 枚举已经隐式继承了 Enum
  • Java 只支持单继承

五、给枚举添加字段和方法(非常重要)

5.1 带字段的枚举

java 复制代码
public enum OrderStatus {

    CREATED(0, "已创建"),
    PAID(1, "已支付"),
    SHIPPED(2, "已发货"),
    FINISHED(3, "已完成");

    private final int code;
    private final String desc;

    //注意私有化构造函数
    private OrderStatus(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public int getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }
}

和单例模式的表达一样,如果想了解单例模式,见【设计模式】理解单例模式:从原理到最佳实践-CSDN博客


5.2 使用示例

java 复制代码
OrderStatus status = OrderStatus.PAID;
System.out.println(status.getCode()); // 1
System.out.println(status.getDesc()); // 已支付

✔ 枚举 ≠ 只能当常量


六、枚举的常用内置方法

6.1 values()

java 复制代码
OrderStatus[] values = OrderStatus.values();

遍历枚举:

java 复制代码
for (OrderStatus s : OrderStatus.values()) {
    System.out.println(s);
}

6.2 valueOf()

java 复制代码
OrderStatus s = OrderStatus.valueOf("PAID");

⚠️ 字符串必须完全匹配,否则抛异常


6.3 name() / ordinal()

java 复制代码
status.name();    // PAID
status.ordinal(); // 1

不推荐使用 ordinal 做业务逻辑


七、枚举实现接口(常见高级用法)

7.1 枚举实现接口

java 复制代码
public interface Operation {
    int apply(int a, int b);
}
java 复制代码
public enum Calculator implements Operation {

    ADD {
        public int apply(int a, int b) {
            return a + b;
        }
    },
    SUB {
        public int apply(int a, int b) {
            return a - b;
        }
    }
}

使用:

java 复制代码
Calculator.ADD.apply(3, 5); // 8

✔ 枚举 + 策略模式


八、枚举与单例模式(最佳实践)

8.1 枚举实现单例(Effective Java 推荐)

java 复制代码
public enum Singleton {
    INSTANCE;

    public void doSomething() {
        System.out.println("do something");
    }
}

优势:

  • 线程安全
  • 防反射
  • 防反序列化破坏

九、枚举的序列化与反序列化安全性

java 复制代码
ObjectInputStream.readObject()
  • 普通单例可能被破坏
  • 枚举 由 JVM 保证只存在一个实例

这是枚举作为单例的核心优势之一。


十、枚举 vs 常量类

对比项 枚举 常量类
类型安全
可读性 一般
扩展能力
switch 支持 原生 需额外处理
单例保证 JVM 需自行实现

参考资料

黑马程序员2026版AI+Java - bilibili.com

枚举类 - Java教程 - 廖雪峰的官方网站

Java 枚举(enum) | 菜鸟教程

相关推荐
老王熬夜敲代码2 小时前
C++新特性:string_view
开发语言·c++·笔记
像风一样的男人@2 小时前
python --生成ico图标
java·python·spring
zhaokuner2 小时前
06-聚合与一致性边界-DDD领域驱动设计
java·开发语言·设计模式·架构
lsx2024063 小时前
Ionic 卡片组件深度解析
开发语言
技术小泽3 小时前
DDD领域设计精讲
java·后端·设计模式·架构
多打代码3 小时前
2026.1.2 删除二叉搜索树中的节点
开发语言·python·算法
一路往蓝-Anbo3 小时前
STM32单线串口通讯实战(二):链路层核心 —— DMA环形缓冲与收发切换时序
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网
萧曵 丶3 小时前
MQ 业务实际使用与问题处理详解
开发语言·kafka·消息队列·rabbitmq·rocketmq·mq
kylezhao20193 小时前
第三节、C# 上位机面向对象编程详解(工控硬件封装实战版)
开发语言·前端·c#