在 Java 中,enum
(枚举)是一种特殊的类,用于定义一组固定的常量。它不仅能替代“魔法值”,还能让代码更安全、更清晰、更易于维护。
本文将带你从零开始,系统学习 Java 枚举的完整语法,包括:基本定义、构造方法、属性、方法、抽象方法、switch 使用等。
一、最简单的枚举定义
使用 enum
关键字定义一组固定值:
public enum Color {
RED, GREEN, BLUE
}
说明:
Color
是一个枚举类型。RED
、GREEN
、BLUE
是这个类型的唯一实例(也是常量)。- 每个值都是
Color
类型的对象。
使用方式:
Color c = Color.RED;
System.out.println(c); // 输出:RED
二、枚举的本质:它是一个类!
虽然写法简单,但 enum
其实是一个编译器自动生成的类,它隐式继承了 java.lang.Enum
。
所以你可以在枚举中添加:
- 属性(fields)
- 构造方法(constructor)
- 方法(methods)
- 甚至抽象方法!
三、带属性和构造方法的枚举
最常见的用法:为每个枚举值绑定额外信息,比如中文描述、数据库编码等。
public enum OrderStatus {
PENDING(0, "待支付"),
PAID(1, "已支付"),
SHIPPED(2, "已发货"),
COMPLETED(3, "已完成"),
CANCELLED(-1, "已取消");
private final int code;
private final String desc;
// 构造方法必须是 private(枚举不能被外部实例化)
OrderStatus(int code, String desc) {
this.code = code;
this.desc = desc;
}
// getter 方法
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
使用示例:
OrderStatus status = OrderStatus.PAID;
System.out.println(status.getCode()); // 输出:1
System.out.println(status.getDesc()); // 输出:已支付
System.out.println(status.name()); // 输出:PAID
System.out.println(status.ordinal()); // 输出:1(索引,从0开始)
四、枚举的常用内置方法
所有枚举都自动拥有以下方法:
方法 | 说明 |
---|---|
name() | 返回枚举常量的名称(字符串) |
ordinal() | 返回该常量在枚举中的位置(从 0 开始) |
values() | 返回枚举所有值的数组(静态方法) |
valueOf(String) | 根据名称返回对应枚举值 |
示例:
// 遍历所有状态
for (OrderStatus s : OrderStatus.values()) {
System.out.println(s + " -> " + s.getDesc());
}
// 字符串转枚举
OrderStatus status = OrderStatus.valueOf("PAID"); // 注意:大小写敏感!
⚠️ 如果 valueOf("XXX")
找不到,会抛出 IllegalArgumentException
!
五、自定义转换方法(推荐实践)
通常前端传的是 code
,我们想根据 code
找到枚举值。
public static OrderStatus fromCode(int code) {
for (OrderStatus status : OrderStatus.values()) {
if (status.code == code) {
return status;
}
}
throw new IllegalArgumentException("无效状态码:" + code);
}
使用:
OrderStatus status = OrderStatus.fromCode(1); // 返回 PAID
六、枚举中的抽象方法(高级用法)
你可以让每个枚举值实现不同的行为。
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);
}
使用:
double result = Operation.TIMES.apply(5, 3); // 输出:15.0
✅ 适用场景:策略模式、不同类型的处理逻辑。
七、在 switch 中使用枚举(推荐)
枚举非常适合与 switch
搭配,代码清晰又安全。
OrderStatus status = OrderStatus.PAID;
switch (status) {
case PENDING:
System.out.println("等待付款");
break;
case PAID:
System.out.println("准备发货");
break;
case SHIPPED:
System.out.println("运输中");
break;
case COMPLETED:
case CANCELLED:
System.out.println("订单结束");
break;
default:
throw new AssertionError("未知状态:" + status);
}
优点:
- 不需要
break
漏了会警告(现代 IDE) - 编译器可检查是否覆盖所有情况
八、枚举的注意事项
注意项 | 说明 |
---|---|
不能继承 | 枚举是 final 的,不能被继承 |
可以实现接口 | public enum Color implements Serializable |
构造方法必须是 private | 不能外部创建新实例 |
ordinal() 谨慎使用 | 它依赖定义顺序,重构时可能出错 |
推荐存 code 到数据库 | 而不是 name() 或 ordinal() |
九、完整语法结构总结
public enum 枚举名 {
// 枚举常量(必须放在最前面)
常量1(参数),
常量2(参数),
常量3(参数);
// 属性
private final 类型 字段;
// 构造方法(private 可省略)
枚举名(参数) {
this.字段 = 值;
}
// 方法
public 类型 getXXX() { ... }
// 静态方法
public static 枚举名 fromXXX(参数) { ... }
// 抽象方法(可选)
public abstract void doSomething();
}
十、总结:枚举的核心语法要点
要点 | 说明 |
---|---|
使用 enum 关键字 | 定义枚举类型 |
常量写在最前面 | 用逗号分隔,分号结尾 |
可以有构造方法 | 必须是 private |
可以有属性和方法 | 就像普通类一样 |
支持抽象方法 | 实现不同行为 |
内置 values() 和 valueOf() | 方便遍历和查找 |
推荐绑定业务 code | 便于数据库存储和传输 |
记住一句话:枚举 = 固定常量 + 类的功能
当你需要表示“有限且不变的选项”时,就该用 enum
了!