源本科技 | 码上会

Java 枚举与自定义异常

2026/01/31
41
0

枚举的基本定义

基本语法

public enum EnumName {
    CONSTANT1,
    CONSTANT2,
    // ... 更多常量
}
  • EnumName:枚举类型名称,首字母大写(符合类命名规范)

  • CONSTANT1, CONSTANT2, ...:枚举常量,全部大写,多单词用下划线分隔(如 HTTP_OK

示例:简单星期枚举

public enum DayOfWeek {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

迭代所有枚举值:调用 DayOfWeek.values() 返回一个包含所有枚举常量的数组。


K-V 模式:带属性的枚举

实际开发中,枚举常需携带额外信息(如编码、描述等),可通过构造器和字段实现:

public enum WeekDayEnum {
    MONDAY(1, "星期一"),
    TUESDAY(2, "星期二"),
    WEDNESDAY(3, "星期三"),
    THURSDAY(4, "星期四"),
    FRIDAY(5, "星期五"),
    SATURDAY(6, "星期六"),
    SUNDAY(0, "星期日");

    private final int key;
    private final String value;

    WeekDayEnum(int key, String value) {
        this.key = key;
        this.value = value;
    }

    public int getKey() { return key; }
    public String getValue() { return value; }

    // 可选:根据 key 查找枚举(静态工具方法)
    public static WeekDayEnum fromKey(int key) {
        for (WeekDayEnum day : values()) {
            if (day.key == key) {
                return day;
            }
        }
        throw new IllegalArgumentException("无效的星期键: " + key);
    }
}

枚举的特征

特性

说明

继承自 java.lang.Enum

所有枚举隐式继承 Enum,不能继承其他类

final 类型

枚举类自动为 final,不可被继承

私有构造器

枚举构造器必须是 private(默认即私有),外部无法 new 实例

实例在首行声明

枚举常量必须在类体第一行显式列出

多例模式

枚举是“多例模式”的天然实现 —— 固定数量的实例


实战练习:数字转星期

需求

用户输入 1~7 的整数,输出对应中文星期名称,使用枚举实现。

实现

import java.util.Scanner;

enum DayOfWeek {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

public class WeekdayChecker {
    public static DayOfWeek getDayOfWeek(int dayNumber) {
        if (dayNumber < 1 || dayNumber > 7) {
            return null;
        }
        return DayOfWeek.values()[dayNumber - 1]; // 利用数组索引,更简洁
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入一个数字(1 到 7):");
        int dayNumber = scanner.nextInt();

        DayOfWeek day = getDayOfWeek(dayNumber);
        if (day != null) {
            System.out.println("对应的星期几是:" + day);
        } else {
            System.out.println("输入无效的数字");
        }
    }
}

枚举与自定义异常

在企业级开发中,枚举常与自定义异常结合,用于统一管理错误码和错误信息。

异常分类(常见三种)

类型

说明

示例

系统异常

JVM 或底层故障,通常不可恢复

OutOfMemoryError

业务异常

业务规则不满足,需提示用户

“余额不足”、“订单已取消”

用户异常

用户输入错误或权限不足

“用户名不存在”、“密码错误”


定义错误码枚举

public enum ErrorCodeEnum {
    // 系统级错误(5xx)
    SYSTEM_ERROR(50000, "系统内部错误", "系统异常"),
    DATABASE_ERROR(50001, "数据库访问异常", "系统异常"),

    // 业务逻辑错误(4xx)
    INVALID_INPUT(40001, "输入参数无效", "业务异常"),
    INSUFFICIENT_BALANCE(40002, "账户余额不足", "业务异常"),

    // 用户操作错误(4xx)
    USER_NOT_FOUND(40101, "用户不存在", "用户异常"),
    INVALID_CREDENTIALS(40102, "用户名或密码错误", "用户异常"),
    PERMISSION_DENIED(40301, "无权访问该资源", "用户异常");

    private final int code;
    private final String message;
    private final String category; // 异常类别:系统/业务/用户

    ErrorCodeEnum(int code, String message, String category) {
        this.code = code;
        this.message = message;
        this.category = category;
    }

    public int getCode() { return code; }
    public String getMessage() { return message; }
    public String getCategory() { return category; }
}

自定义异常基类

public class BusinessException extends RuntimeException {
    private final int errorCode;
    private final String errorCategory;

    public BusinessException(ErrorCodeEnum error) {
        super(error.getMessage());
        this.errorCode = error.getCode();
        this.errorCategory = error.getCategory();
    }

    public int getErrorCode() { return errorCode; }
    public String getErrorCategory() { return errorCategory; }
}

所有业务相关异常都继承此类,携带结构化错误信息。


在星期转换中集成异常处理

改造之前的 WeekdayChecker,使用错误码枚举抛出异常:

public class WeekdayService {

    public static String getChineseWeekday(int dayNumber) {
        if (dayNumber < 1 || dayNumber > 7) {
            throw new BusinessException(ErrorCodeEnum.INVALID_INPUT);
        }
        // 使用 K-V 枚举更直观
        return WeekDayEnum.values()[dayNumber - 1].getValue();
    }
}

// 主程序
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入一个数字(1 到 7):");
        try {
            int input = scanner.nextInt();
            String weekday = WeekdayService.getChineseWeekday(input);
            System.out.println("对应的星期是:" + weekday);
        } catch (BusinessException e) {
            System.err.printf("[错误码 %d][%s] %s%n",
                e.getErrorCode(),
                e.getErrorCategory(),
                e.getMessage()
            );
        } catch (Exception e) {
            // 捕获非预期异常(如输入非数字)
            System.err.println("[系统错误] 输入格式不正确,请输入整数");
        }
    }
}

运行示例

请输入一个数字(1 到 7):8
[错误码 40001][业务异常] 输入参数无效

总结

技术点

价值

枚举

提供类型安全的常量集合,替代魔法数字 / 字符串

K-V 枚举

携带元数据,增强语义表达

错误码枚举 + 自定义异常

统一异常管理,便于日志、监控、前端提示

异常分类

清晰区分系统、业务、用户问题,利于运维和产品优化

通过枚举与异常的有机结合,可构建高内聚、低耦合、易维护的企业级 Java 应用。