第24篇:Java枚举类型 enum 用法


📌 系列导航《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第23篇:缓冲区数据结构 ByteBuffer |
➡️ 下一篇:第25篇:Java类加载与初始化


一、核心知识点

  • enum 的定义和使用
  • enum 的构造器、成员变量和方法
  • enum 的特性:不能继承(隐式继承 Enum),可以实现接口
  • values()valueOf()ordinal() 方法
  • EnumSetEnumMap 简介
  • 枚举单例模式

二、通俗讲解(1分钟开心学)

1. 枚举是什么?

枚举是一种特殊的类,用来定义一组常量。比如星期、季节、状态等。使用枚举可以让代码更清晰、类型安全。

2. 枚举的本质

  • 枚举常量是 public static final 的实例,在类加载时创建。
  • 枚举的构造器必须是 private(默认也是 private),不允许外部创建新实例。
  • 枚举可以定义成员变量、方法,甚至抽象方法(每个常量单独实现)。

3. 常用内置方法

  • values():返回所有枚举常量的数组(顺序为声明顺序)。
  • valueOf(String name):根据名称获取枚举常量,不存在抛 IllegalArgumentException
  • ordinal():返回声明顺序索引(从0开始),不建议用于业务逻辑。

4. 枚举的高级用法

  • 实现接口:枚举可以实现接口,所有常量共享该接口方法,也可以各自重写。
  • 枚举单例:枚举单例是线程安全的,且能防止反射攻击,是推荐的单例实现方式。

生活类比
枚举就像一本“日历”,已经印好了周一到周日。你不能自己再创建一个“星期八”。每种星期几都是一个固定的对象。

三、实操代码案例 + 场景说明

场景:定义一个订单状态枚举,包含状态转换逻辑。

public enum OrderStatus {
    PENDING(0, "待支付"),
    PAID(1, "已支付"),
    SHIPPED(2, "已发货"),
    COMPLETED(3, "已完成"),
    CANCELLED(4, "已取消");
    
    private final int code;
    private final String desc;
    
    OrderStatus(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }
    
    public int getCode() { return code; }
    public String getDesc() { return desc; }
    
    // 根据code获取枚举
    public static OrderStatus fromCode(int code) {
        for (OrderStatus status : values()) {
            if (status.code == code) return status;
        }
        throw new IllegalArgumentException("未知状态码: " + code);
    }
    
    // 判断是否可取消
    public boolean canCancel() {
        return this == PENDING;
    }
}

// 使用示例
public class EnumDemo {
    public static void main(String[] args) {
        OrderStatus status = OrderStatus.PAID;
        System.out.println(status.getDesc()); // 已支付
        System.out.println(status.canCancel()); // false
        
        // 遍历
        for (OrderStatus s : OrderStatus.values()) {
            System.out.println(s.name() + "(" + s.getCode() + ")");
        }
        
        // 根据名称获取
        OrderStatus pending = OrderStatus.valueOf("PENDING");
        System.out.println(pending.getDesc());
        
        // 单例枚举
        Singleton.INSTANCE.doSomething();
    }
}

// 枚举单例
enum Singleton {
    INSTANCE;
    public void doSomething() {
        System.out.println("单例方法调用");
    }
}

四、避坑要点

错误/误区 后果 正确做法
使用 ordinal() 做业务逻辑 顺序调整后逻辑错误 使用自定义 code 或名称
枚举构造器写成 public 编译错误 构造器只能是 private(默认)
== 比较枚举(可以,但不了解原因会觉得奇怪) 没问题,推荐用 == 枚举常量是单例,== 安全且高效
枚举实现接口时,不同常量可以有不同行为? 可以,使用匿名内部类方式 在常量后跟 { } 实现抽象方法

五、面试高频考点

Q1:枚举如何保证线程安全?

枚举常量是在类加载时由 JVM 创建和初始化的,属于静态成员,JVM 保证类加载的线程安全,因此枚举单例是线程安全的。

Q2:枚举能否继承其他类?能否实现接口?

不能继承其他类(隐式继承了 java.lang.Enum),但可以实现多个接口。

Q3:EnumSetEnumMap 的优势?

它们是专为枚举设计的集合,内部使用位向量或数组实现,比普通 HashSet/HashMap 更高效,内存占用更小。

六、练习题

  1. 设计:定义一个 Weekday 枚举,包含星期一到星期日,添加一个方法 isWeekend() 判断是否为周末。
  2. 代码补全:实现一个 Calculator 枚举,每个常量代表一种运算(加、减、乘、除),包含 apply(double a, double b) 方法。
  3. 简答:为什么推荐用枚举实现单例?

📊 你的学习进度

  • 当前:第24篇 / 共44篇 · 第三阶段:字符串、Buffer、枚举、类加载(第21~25篇)
  • ✅ 已完成:第1~23篇
  • 📖 正在学:第24篇
  • ⏳ 待学习:第25~44篇

👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇

💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!


下一篇文章预告

《Java类加载与初始化》

内容简介:类加载生命周期(加载→验证→准备→解析→初始化),类加载器与双亲委派模型,主动/被动引用。

💡 学完这篇,你将彻底搞懂Java类是如何加载的,面试必考的类加载器问题轻松拿下。

📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!


Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐