Java 枚举(enum)
枚举是 Java 5 引入的特殊类,用于定义一组固定的常量。理解枚举的使用是编写类型安全代码的关键。本章将详细介绍 Java 中的枚举。
枚举的概念
什么是枚举
枚举(Enum)是一种特殊的类,用于定义一组固定的常量值。
// 定义枚举
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
// 使用枚举
Season currentSeason = Season.SPRING;
System.out.println(currentSeason); // SPRING
为什么使用枚举
枚举的优势:
- 类型安全:编译时检查,避免无效值
- 代码清晰:比魔法数字和字符串更清晰
- 功能强大:可以有方法、属性、构造方法
- 单例模式:每个枚举值都是单例
基本枚举
简单枚举
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
// 使用
Day today = Day.MONDAY;
if (today == Day.MONDAY) {
System.out.println("今天是星期一");
}
枚举的常用方法
public enum Day {
MONDAY, TUESDAY, WEDNESDAY
}
// 获取所有枚举值
Day[] days = Day.values();
for (Day day : days) {
System.out.println(day);
}
// 根据名称获取枚举值
Day day = Day.valueOf("MONDAY");
// 获取枚举值的名称
String name = Day.MONDAY.name(); // "MONDAY"
// 获取枚举值的序号
int ordinal = Day.MONDAY.ordinal(); // 0
高级枚举
枚举可以有属性
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);
private final double mass; // 质量
private final double radius; // 半径
// 构造方法
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
// Getter 方法
public double getMass() {
return mass;
}
public double getRadius() {
return radius;
}
// 计算方法
public double getSurfaceGravity() {
double G = 6.67300E-11;
return G * mass / (radius * radius);
}
}
// 使用
Planet earth = Planet.EARTH;
System.out.println("地球质量:" + earth.getMass());
System.out.println("地球表面重力:" + earth.getSurfaceGravity());
枚举可以有方法
public enum Operation {
PLUS {
@Override
public double apply(double x, double y) {
return x + y;
}
},
MINUS {
@Override
public double apply(double x, double y) {
return x - y;
}
},
MULTIPLY {
@Override
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE {
@Override
public double apply(double x, double y) {
return x / y;
}
};
// 抽象方法:每个枚举值必须实现
public abstract double apply(double x, double y);
}
// 使用
double result = Operation.PLUS.apply(10, 5); // 15
枚举可以实现接口
public interface Describable {
String getDescription();
}
public enum Status implements Describable {
ACTIVE("激活状态"),
INACTIVE("未激活状态"),
PENDING("待处理状态");
private final String description;
Status(String description) {
this.description = description;
}
@Override
public String getDescription() {
return description;
}
}
// 使用
Status status = Status.ACTIVE;
System.out.println(status.getDescription()); // "激活状态"
枚举的使用场景
1. 状态定义
public enum OrderStatus {
PENDING, // 待处理
PROCESSING, // 处理中
SHIPPED, // 已发货
DELIVERED, // 已送达
CANCELLED // 已取消
}
public class Order {
private OrderStatus status;
public void setStatus(OrderStatus status) {
this.status = status;
}
public OrderStatus getStatus() {
return status;
}
}
2. 配置选项
public enum LogLevel {
DEBUG, INFO, WARNING, ERROR
}
public class Logger {
private LogLevel level;
public void log(String message, LogLevel level) {
if (level.ordinal() >= this.level.ordinal()) {
System.out.println("[" + level + "] " + message);
}
}
}
3. 单例模式
public enum Singleton {
INSTANCE;
private String data;
public void setData(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
// 使用
Singleton.INSTANCE.setData("数据");
String data = Singleton.INSTANCE.getData();
枚举的常用方法
values() 方法
获取所有枚举值:
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Day[] days = Day.values();
for (Day day : days) {
System.out.println(day);
}
valueOf() 方法
根据名称获取枚举值:
Day day = Day.valueOf("MONDAY"); // 返回 Day.MONDAY
// 如果名称不存在,抛出 IllegalArgumentException
// Day invalid = Day.valueOf("INVALID"); // 抛出异常
name() 和 ordinal() 方法
Day day = Day.MONDAY;
String name = day.name(); // "MONDAY"
int ordinal = day.ordinal(); // 0(第一个枚举值的序号是 0)
compareTo() 方法
比较枚举值的顺序:
Day monday = Day.MONDAY;
Day friday = Day.FRIDAY;
int result = monday.compareTo(friday); // 负数(MONDAY 在 FRIDAY 之前)
实际示例
示例 1:完整的枚举
public enum HttpStatus {
OK(200, "成功"),
NOT_FOUND(404, "未找到"),
INTERNAL_ERROR(500, "服务器错误");
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);
}
}
// 使用
HttpStatus status = HttpStatus.OK;
System.out.println(status.getCode()); // 200
System.out.println(status.getMessage()); // "成功"
HttpStatus status2 = HttpStatus.fromCode(404);
System.out.println(status2); // NOT_FOUND
示例 2:枚举实现接口
public interface Colorful {
String getColor();
}
public enum TrafficLight implements Colorful {
RED("红色") {
@Override
public String getColor() {
return "红色";
}
},
YELLOW("黄色") {
@Override
public String getColor() {
return "黄色";
}
},
GREEN("绿色") {
@Override
public String getColor() {
return "绿色";
}
};
private final String description;
TrafficLight(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
// 使用
TrafficLight light = TrafficLight.RED;
System.out.println(light.getColor()); // "红色"
System.out.println(light.getDescription()); // "红色"
示例 3:枚举作为单例
public enum DatabaseConnection {
INSTANCE;
private Connection connection;
public void connect() {
// 连接数据库
System.out.println("连接数据库");
}
public void disconnect() {
// 断开连接
System.out.println("断开数据库连接");
}
public Connection getConnection() {
return connection;
}
}
// 使用
DatabaseConnection.INSTANCE.connect();
DatabaseConnection.INSTANCE.disconnect();
枚举 vs 常量类
使用枚举
public enum Status {
ACTIVE, INACTIVE, PENDING
}
使用常量类
public class Status {
public static final int ACTIVE = 1;
public static final int INACTIVE = 2;
public static final int PENDING = 3;
}
对比
| 特性 | 枚举 | 常量类 |
|---|---|---|
| 类型安全 | ✅ | ❌ |
| 编译时检查 | ✅ | ❌ |
| 可以有方法 | ✅ | ❌ |
| 可以有属性 | ✅ | ❌ |
| 单例模式 | ✅ | ❌ |
推荐使用枚举:更安全、更强大、更清晰。
小结
Java 枚举要点:
- 枚举定义:用 enum 关键字,定义固定常量
- 高级特性:可以有属性、方法、构造方法
- 实现接口:枚举可以实现接口
- 常用方法:values()、valueOf()、name()、ordinal()
- 使用场景:状态定义、配置选项、单例模式
关键要点:
- 枚举是类型安全的常量
- 每个枚举值都是单例
- 可以有属性和方法
- 可以实现接口
- 推荐使用枚举替代常量类
理解了枚举,你就能编写更类型安全的代码。在下一章,我们将学习 Java 的注解。