哪些Java案例展示了枚举的用法?

wen java案例 5

本文目录导读:

哪些Java案例展示了枚举的用法?

  1. 基础用法:定义常量
  2. 带字段和构造器的枚举
  3. 实现接口或抽象方法:状态机模式
  4. 策略模式(Switch 替代方案)
  5. 带有反向查找的枚举
  6. 单例模式(最安全的单例之一)
  7. 结合 switch 的简洁用法
  8. 枚举实现多级的国家/地区状态(嵌套枚举)
  9. 推荐用法场景

Java 中的枚举(enum)是一种特殊的类,用于定义一组常量,它比传统的 public static final 常量更强大、更安全,以下是一些经典的 Java 枚举用法案例,涵盖了从基础到进阶的各种场景。


基础用法:定义常量

这是最直接的用法,代替传统的 public static final int

// 传统方式
public static final int STATUS_PENDING = 0;
public static final int STATUS_PROCESSING = 1;
public static final int STATUS_COMPLETED = 2;
// 枚举方式
public enum OrderStatus {
    PENDING,      // 待处理
    PROCESSING,   // 处理中
    COMPLETED,    // 已完成
    CANCELLED     // 已取消
}
// 使用
OrderStatus currentStatus = OrderStatus.PENDING;
if (currentStatus == OrderStatus.COMPLETED) {
    System.out.println("订单已完成");
}

优点:类型安全、可读性强、自带 name()ordinal() 方法。


带字段和构造器的枚举

枚举可以像普通类一样有字段、构造器和方法,常用于将业务代码与枚举值绑定。

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),
    JUPITER(1.9e+27, 7.1492e7),
    SATURN(5.688e+26, 6.0268e7),
    URANUS(8.686e+25, 2.5559e7),
    NEPTUNE(1.024e+26, 2.4746e7);
    private final double mass;   // 质量(千克)
    private final double radius; // 半径(米)
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    public double getMass() { return mass; }
    public double getRadius() { return radius; }
    // 计算表面重力
    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    private static final double G = 6.67300E-11;
    public static void main(String[] args) {
        for (Planet p : Planet.values()) {
            System.out.printf("行星 %s: 质量 %.2e kg, 表面重力 %.2f m/s^2%n",
                p, p.getMass(), p.surfaceGravity());
        }
    }
}

输出

行星 MERCURY: 质量 3.30e+23 kg, 表面重力 3.70 m/s^2
行星 VENUS: 质量 4.87e+24 kg, 表面重力 8.87 m/s^2
...

实现接口或抽象方法:状态机模式

枚举可以定义抽象方法,每个枚举常量可以有自己的实现,非常适合实现简单的状态机。

public enum TrafficLight {
    RED(30) {
        @Override
        public TrafficLight next() {
            return GREEN;
        }
    },
    GREEN(45) {
        @Override
        public TrafficLight next() {
            return YELLOW;
        }
    },
    YELLOW(5) {
        @Override
        public TrafficLight next() {
            return RED;
        }
    };
    private final int duration; // 持续时间(秒)
    TrafficLight(int duration) {
        this.duration = duration;
    }
    public int getDuration() { return duration; }
    // 抽象方法:返回下一个状态
    public abstract TrafficLight next();
}
// 使用
TrafficLight light = TrafficLight.RED;
System.out.println("当前: " + light + " (" + light.getDuration() + "秒)");
light = light.next();
System.out.println("下一个: " + light + " (" + light.getDuration() + "秒)");

输出

当前: RED (30秒)
下一个: GREEN (45秒)

策略模式(Switch 替代方案)

用枚举消除冗长的 switchif-else 业务逻辑。

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;
        }
    },
    TIMES {
        @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);
}
// 使用
Operation op = Operation.PLUS;
double result = op.apply(10, 5); // 15

优势:新增操作只需在枚举中添加一个新常量并实现 apply 方法,无需修改业务逻辑代码,符合开闭原则。


带有反向查找的枚举

根据业务字段(如代码、标签)查找枚举实例,常用于数据库持久化或对外接口。

public enum StatusCode {
    SUCCESS(0, "成功"),
    FAIL(1, "失败"),
    TIMEOUT(2, "超时"),
    UNKNOWN_ERROR(99, "未知错误");
    private final int code;
    private final String description;
    StatusCode(int code, String description) {
        this.code = code;
        this.description = description;
    }
    public int getCode() { return code; }
    public String getDescription() { return description; }
    // 根据 code 反向查找枚举
    public static StatusCode fromCode(int code) {
        for (StatusCode s : StatusCode.values()) {
            if (s.code == code) {
                return s;
            }
        }
        throw new IllegalArgumentException("未知状态码: " + code);
    }
}
// 使用
StatusCode status = StatusCode.fromCode(2);
System.out.println(status.getDescription()); // 超时

单例模式(最安全的单例之一)

枚举天然支持单例,且能防止反射攻击和序列化破坏。

public enum Singleton {
    INSTANCE;
    private final String data = "共享数据";
    public String getData() {
        return data;
    }
    public void doSomething() {
        System.out.println("执行单例方法");
    }
}
// 使用
Singleton singleton = Singleton.INSTANCE;
singleton.doSomething();

为什么安全:JVM 保证枚举实例唯一创建,readResolve 机制自动处理序列化,反射 newInstance 会直接抛出 IllegalArgumentException


结合 switch 的简洁用法

虽然枚举可以自带方法,但在很多简单脚本式代码中搭配 switch 仍然很方便。

public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
// 使用
Day day = Day.SATURDAY;
switch (day) {
    case MONDAY:
    case TUESDAY:
    case WEDNESDAY:
    case THURSDAY:
    case FRIDAY:
        System.out.println("工作日");
        break;
    case SATURDAY:
    case SUNDAY:
        System.out.println("周末");
        break;
}

注意switch 使用枚举时,case 中不需要写枚举类型名(如 Day.MONDAYMONDAY),因为编译器已经知道上下文。


枚举实现多级的国家/地区状态(嵌套枚举)

枚举可以包含枚举,实现更复杂的常量分类。

public enum Country {
    CHINA("中国") {
        @Override
        public Province[] getProvinces() {
            return Province.values(); // 只包含中国省份
        }
    },
    USA("美国") {
        @Override
        public Province[] getProvinces() {
            return new Province[0]; // 美国没有省份(实际有州,这里简化)
        }
    };
    private final String chineseName;
    Country(String chineseName) {
        this.chineseName = chineseName;
    }
    public String getChineseName() { return chineseName; }
    // 抽象方法:每个国家返回自己的省级枚举
    public abstract Province[] getProvinces();
    // 省份枚举(嵌套在 Country 中,也可以独立)
    public enum Province {
        BEIJING("北京"),
        SHANGHAI("上海"),
        GUANGDONG("广东");
        // ...
        Province(String name) { this.name = name; }
        private final String name;
        public String getName() { return name; }
    }
}
// 使用
Country country = Country.CHINA;
for (Country.Province p : country.getProvinces()) {
    System.out.println(country.getChineseName() + " -> " + p.getName());
}

推荐用法场景

场景 推荐枚举用法 案例参考
一组简单常量 基础枚举 案例 1
常量携带额外数据 带字段构造器 案例 2
状态流转 / 策略 抽象方法 案例 3, 4
数据库持久化 / 接口 反向查找(fromCode 案例 5
绝对安全的单例 单例枚举 案例 6
简单分支判断 switch + 枚举 案例 7
复杂分类的常量 嵌套枚举 案例 8

枚举是 Java 中非常重要的语言特性,合理使用可以写出更清晰、安全且易于维护的代码。

抱歉,评论功能暂时关闭!