Java 枚举(enum)
2026/4/6 12:20:00 网站建设 项目流程
Java 枚举 (Enum) 学习笔记详细版一、枚举的基本概念1.1 什么是枚举枚举Enum是一种特殊的类用于定义一组固定的常量。在 Java 中枚举类型是java.lang.Enum的子类。枚举常量在编译时确定运行期间不可变。1.2 为什么使用枚举类型安全防止传入非法值如用int表示星期几可能传入 8。代码可读性Day.MONDAY比1更直观。单例模式枚举是实现单例模式最安全、最简单的方式。内置功能提供values(),valueOf(),ordinal()等实用方法。二、枚举的基本语法2.1 简单枚举定义// 定义枚举类型publicenumDay{SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY}// 使用枚举publicclassTest{publicstaticvoidmain(String[]args){DaytodayDay.MONDAY;// 遍历所有枚举值for(Dayday:Day.values()){System.out.println(day);}// 获取枚举的索引从0开始System.out.println(today.ordinal());// 输出 1// 根据字符串获取枚举DaydayFromStringDay.valueOf(FRIDAY);System.out.println(dayFromString);// 输出 FRIDAY}}2.2 枚举的底层原理枚举本质上是final的类隐式继承自java.lang.Enum。枚举常量是public static final的实例。枚举不能继承其他类因为已经继承了 Enum但可以实现接口。三、枚举的高级特性3.1 枚举成员属性枚举可以像普通类一样拥有字段、构造方法、方法和常量。publicenumSeason{// 定义枚举常量并传入参数SPRING(春季,温暖),SUMMER(夏季,炎热),AUTUMN(秋季,凉爽),WINTER(冬季,寒冷);// 成员变量privatefinalStringname;privatefinalStringdescription;// 构造方法必须是 private默认就是 privateSeason(Stringname,Stringdescription){this.namename;this.descriptiondescription;}// Getter 方法publicStringgetName(){returnname;}publicStringgetDescription(){returndescription;}// 重写 toString 方法OverridepublicStringtoString(){returnname (description);}}// 使用publicclassSeasonTest{publicstaticvoidmain(String[]args){SeasonsSeason.SUMMER;System.out.println(s.getName());// 夏季System.out.println(s.getDescription());// 炎热System.out.println(s);// 夏季 (炎热)}}3.2 枚举实现接口枚举可以实现一个或多个接口为每个枚举常量提供不同的实现。interfaceOperation{doubleapply(doublex,doubley);}publicenumMathOperationimplementsOperation{ADD{Overridepublicdoubleapply(doublex,doubley){returnxy;}},SUBTRACT{Overridepublicdoubleapply(doublex,doubley){returnx-y;}},MULTIPLY{Overridepublicdoubleapply(doublex,doubley){returnx*y;}},DIVIDE{Overridepublicdoubleapply(doublex,doubley){if(y0)thrownewArithmeticException(除数不能为0);returnx/y;}};// 枚举也可以有普通方法publicvoidprintInfo(){System.out.println(执行操作this.name());}}// 使用publicclassOperationTest{publicstaticvoidmain(String[]args){MathOperationopMathOperation.MULTIPLY;System.out.println(op.apply(5,3));// 15.0op.printInfo();}}3.3 枚举的 switch 语句枚举在switch语句中非常常用代码清晰且类型安全。publicenumStatus{PENDING,PROCESSING,COMPLETED,FAILED}publicclassStatusHandler{publicvoidhandleStatus(Statusstatus){switch(status){casePENDING:System.out.println(等待处理...);break;casePROCESSING:System.out.println(正在处理...);break;caseCOMPLETED:System.out.println(处理完成);break;caseFAILED:System.out.println(处理失败);break;default:System.out.println(未知状态);}}}四、枚举的常用方法方法名说明示例values()返回所有枚举常量的数组Day.values()valueOf(String name)根据名称返回枚举常量Day.valueOf(MONDAY)ordinal()返回枚举常量的索引从0开始Day.MONDAY.ordinal()- 1name()返回枚举常量的字符串名称Day.MONDAY.name()- “MONDAY”compareTo(E other)比较两个枚举常量的顺序Day.MONDAY.compareTo(Day.TUESDAY)equals(Object obj)判断两个枚举是否相同Day.MONDAY.equals(Day.MONDAY)五、枚举的高级应用5.1 单例模式Enum Singleton推荐方式使用枚举实现单例模式天然防止反射和序列化攻击。publicenumSingleton{INSTANCE;privateStringdata;publicvoiddoSomething(){System.out.println(执行单例操作: data);}publicstaticvoidmain(String[]args){Singleton.INSTANCE.dataHello Enum;Singleton.INSTANCE.doSomething();// 验证单例Singletons1Singleton.INSTANCE;Singletons2Singleton.INSTANCE;System.out.println(s1s2);// true}}5.2 状态机State Machine利用枚举管理复杂的状态流转。publicenumOrderStatus{CREATED{OverridepublicOrderStatusnext(){returnPAID;}},PAID{OverridepublicOrderStatusnext(){returnSHIPPED;}},SHIPPED{OverridepublicOrderStatusnext(){returnDELIVERED;}},DELIVERED{OverridepublicOrderStatusnext(){returnthis;// 结束状态}};publicabstractOrderStatusnext();}// 使用publicclassOrder{privateOrderStatusstatusOrderStatus.CREATED;publicvoidprocess(){statusstatus.next();System.out.println(订单状态变为status);}}5.3 策略模式Strategy Pattern枚举作为策略的载体替代传统的类实现。publicenumDiscountStrategy{NONE(0.0){OverridepublicdoubleapplyDiscount(doubleprice){returnprice;}},TEN_PERCENT(0.1){OverridepublicdoubleapplyDiscount(doubleprice){returnprice*(1-0.1);}},HALF_PRICE(0.5){OverridepublicdoubleapplyDiscount(doubleprice){returnprice*(1-0.5);}};privatefinaldoublerate;DiscountStrategy(doublerate){this.raterate;}publicabstractdoubleapplyDiscount(doubleprice);}六、枚举 vs 常量类6.1 传统常量类不推荐publicclassColors{publicstaticfinalintRED0xFF0000;publicstaticfinalintGREEN0x00FF00;publicstaticfinalintBLUE0x0000FF;}// 缺点类型不安全容易混淆无法遍历6.2 枚举常量推荐publicenumColor{RED(0xFF0000),GREEN(0x00FF00),BLUE(0x0000FF);privatefinalintcode;Color(intcode){this.codecode;}publicintgetCode(){returncode;}}// 优点类型安全可遍历可附加行为七、枚举的注意事项7.1 常见陷阱序列化问题枚举天然支持序列化不需要额外处理。反射攻击枚举无法通过反射创建新实例安全性高。线程安全枚举实例是线程安全的。内存占用枚举常量在类加载时初始化占用内存固定。7.2 最佳实践命名规范枚举常量通常全大写单词间用下划线分隔。避免过多逻辑枚举适合表示状态、类型等复杂逻辑建议用策略模式。使用 switch 时确保覆盖所有枚举值或使用default分支。性能优化枚举的ordinal()方法返回的是索引不要依赖它作为业务逻辑依据因为顺序可能变化。八、实战案例订单系统// 定义订单状态publicenumOrderState{CREATED,PAID,SHIPPED,DELIVERED,CANCELLED;// 状态流转规则publicbooleancanTransitionTo(OrderStatenextState){switch(this){caseCREATED:returnnextStatePAID||nextStateCANCELLED;casePAID:returnnextStateSHIPPED||nextStateCANCELLED;caseSHIPPED:returnnextStateDELIVERED;caseDELIVERED:caseCANCELLED:returnfalse;// 终态default:returnfalse;}}}// 订单类publicclassOrder{privateStringorderId;privateOrderStatestate;publicOrder(StringorderId){this.orderIdorderId;this.stateOrderState.CREATED;}publicbooleantransitionTo(OrderStatenextState){if(state.canTransitionTo(nextState)){this.statenextState;System.out.println(订单 orderId 状态更新为nextState);returntrue;}else{System.out.println(订单 orderId 无法从 state 转移到 nextState);returnfalse;}}publicOrderStategetState(){returnstate;}}// 测试publicclassOrderTest{publicstaticvoidmain(String[]args){OrderordernewOrder(ORD001);order.transitionTo(OrderState.PAID);order.transitionTo(OrderState.SHIPPED);order.transitionTo(OrderState.DELIVERED);order.transitionTo(OrderState.CANCELLED);// 失败}}九、常见面试题枚举的底层实现原理是什么枚举是final类继承自Enum常量是static final实例。枚举如何实现单例为什么比传统方式好使用INSTANCE常量JVM 保证线程安全防止反射和序列化攻击。枚举可以继承其他类吗可以实现接口吗不能继承其他类已继承 Enum但可以实现多个接口。枚举的ordinal()方法有什么风险依赖索引顺序如果枚举常量顺序改变逻辑会出错。如何在枚举中添加自定义方法定义构造方法、成员变量和实例方法。十、总结枚举是 Java 中定义常量集合的最佳方式。支持属性、构造方法、方法、接口实现功能强大。适用于状态机、策略模式、单例模式等场景。相比常量类枚举具有类型安全、可遍历、可扩展等优势。掌握枚举的高级用法能显著提升代码的健壮性和可维护性。这份笔记涵盖了 Java 枚举从基础到高级的所有核心知识点建议结合代码实践加深理解

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询