背景与动机
有些数据的取值范围是固定的,比如星期、订单状态、季节、支付方式。这类场景如果只用字符串或整数常量,代码容易写错,也不够直观。
枚举类就是为这类“取值有限、语义明确”的场景准备的。
核心原理拆解
1. enum 用来定义固定常量集合
enum Season { SPRING, SUMMER, AUTUMN, WINTER}这里的四个枚举常量不是普通字符串,而是 Season 类型的四个固定对象。
2. 枚举比字符串常量更安全
Season season = Season.SPRING;如果用字符串,很容易写成 "sprng" 这种拼写错误;用枚举时,编译器就能帮你发现问题。
3. 枚举可以有字段、方法、构造方法
枚举本质上也是一种特殊类,所以不只是“列几个常量”:
enum Status { CREATED("已创建"), PAID("已支付"), FINISHED("已完成");
private final String text;
Status(String text) { this.text = text; }
public String getText() { return text; }}枚举构造方法默认是私有的,不能手动 new。
4. 枚举常和 switch 一起使用
switch (status) { case CREATED: System.out.println("待付款"); break; case PAID: System.out.println("待发货"); break; case FINISHED: System.out.println("已完成"); break;}这让状态分支比字符串判断更清晰、更安全。
5. 枚举自带一些常用方法
Status s = Status.valueOf("PAID");Status[] values = Status.values();System.out.println(s.name());System.out.println(s.ordinal());常见方法含义:
values():返回全部枚举常量valueOf(String):按名字取枚举常量name():返回常量名ordinal():返回声明顺序下标
实际业务里可以了解 ordinal(),但不建议把它当稳定业务值长期依赖。
最小可运行代码示例
public class EnumDemo { public static void main(String[] args) { Status status = Status.PAID;
System.out.println(status.getText());
for (Status item : Status.values()) { System.out.println(item.name()); } }}
enum Status { CREATED("已创建"), PAID("已支付"), FINISHED("已完成");
private final String text;
Status(String text) { this.text = text; }
public String getText() { return text; }}常见陷阱与错误示例
1. 把枚举继续当字符串用
如果已经定义了枚举,却还在代码里到处传 "PAID"、"FINISHED" 这样的字符串,就等于没真正用好枚举。
2. 依赖 ordinal() 做持久化业务值
ordinal() 只是声明顺序下标,如果以后枚举常量顺序改了,业务值就会变,不够稳定。
3. 试图手动 new 枚举对象
枚举对象由 Java 语言层面控制创建,不能像普通类那样手动 new。
面试高频问题
1. 枚举类和普通常量相比有什么优势
枚举有类型约束、语义更清晰、编译期更安全,还能挂字段和方法,表达能力比字符串常量或整数常量更强。
2. 为什么说枚举本质上也是类
因为枚举可以有字段、方法、构造方法,也能实现接口,只是它的实例数量被限制为固定几个常量对象。
3. 为什么不建议用 ordinal() 表示业务状态值
因为它依赖声明顺序,一旦枚举顺序调整,原有业务值就可能错位。
一句话总结
枚举类适合表达“取值有限且语义固定”的数据,比字符串常量更安全、也更容易维护。