java中的枚举类你真的了解过吗

摘要:方法名描述name返回枚举常量的名称(定义时的字符串)。ordinal返回枚举常量的序号,从 0 开始。values返回包含所有枚举常量的数组。valueOf(String name)根据名称返回对应的枚举常量,名称必须匹配。

Java 枚举(enum) 是一种特殊的类,用于表示固定数量的常量集合。例如,季节(春、夏、秋、冬)、方向(东、南、西、北)等情况都可以使用枚举。

Java 枚举在语法上使用 enum 关键字定义。枚举不仅是常量集合,它本质上是一个类,可以包含字段、方法、构造函数等功能。

枚举的特点

1. 枚举是一种类

• 每个枚举常量都是枚举类的实例。

• 枚举不能继承其他类(因为枚举隐式继承 java.lang.Enum),但可以实现接口。

2. 线程安全

• 枚举是线程安全的,因为它是不可变的。

3. 限制实例数量

• 枚举的常量是有限且固定的,不能动态创建新的枚举实例。

4. 枚举的用途

• 表示固定集合(如季节、方向)。

• 实现单例模式(利用枚举的唯一性)。

public enum Season { Spring, Summer, Autumn, Winter,}

• Spring, Summer, Autumn, Winter 是枚举实例。

• 每个枚举实例本质上是 Season 类型的常量。

反编译之后看枚举的类的真实面目:

jay@MacBook-Air forum % javap -c Season.class Compiled from "Season.java"public final class com.lglg.community.api.forum.Season extends java.lang.Enum { public static final com.lglg.community.api.forum.Season Spring; public static final com.lglg.community.api.forum.Season Summer; public static final com.lglg.community.api.forum.Season Autumn; public static final com.lglg.community.api.forum.Season Winter; public static com.lglg.community.api.forum.Season values; Code: 0: getstatic #1 // Field $VALUES:[Lcom/lglg/community/api/forum/Season; 3: invokevirtual #2 // Method "[Lcom/lglg/community/api/forum/Season;".clone:Ljava/lang/Object; 6: checkcast #3 // class "[Lcom/lglg/community/api/forum/Season;" 9: areturn public static com.lglg.community.api.forum.Season valueOf(java.lang.String); Code: 0: ldc #4 // class com/lglg/community/api/forum/Season 2: aload_0 3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; 6: checkcast #4 // class com/lglg/community/api/forum/Season 9: areturn static {}; Code: 0: new #4 // class com/lglg/community/api/forum/Season 3: dup 4: ldc #7 // String Spring 6: iconst_0 7: invokespecial #8 // Method "":(Ljava/lang/String;I)V 10: putstatic #9 // Field Spring:Lcom/lglg/community/api/forum/Season; 13: new #4 // class com/lglg/community/api/forum/Season 16: dup 17: ldc #10 // String Summer 19: iconst_1 20: invokespecial #8 // Method "":(Ljava/lang/String;I)V 23: putstatic #11 // Field Summer:Lcom/lglg/community/api/forum/Season; 26: new #4 // class com/lglg/community/api/forum/Season 29: dup 30: ldc #12 // String Autumn 32: iconst_2 33: invokespecial #8 // Method "":(Ljava/lang/String;I)V 36: putstatic #13 // Field Autumn:Lcom/lglg/community/api/forum/Season; 39: new #4 // class com/lglg/community/api/forum/Season 42: dup 43: ldc #14 // String Winter 45: iconst_3 46: invokespecial #8 // Method "":(Ljava/lang/String;I)V 49: putstatic #15 // Field Winter:Lcom/lglg/community/api/forum/Season; 52: iconst_4 53: anewarray #4 // class com/lglg/community/api/forum/Season 56: dup 57: iconst_0 58: getstatic #9 // Field Spring:Lcom/lglg/community/api/forum/Season; 61: aastore 62: dup 63: iconst_1 64: getstatic #11 // Field Summer:Lcom/lglg/community/api/forum/Season; 67: aastore 68: dup 69: iconst_2 70: getstatic #13 // Field Autumn:Lcom/lglg/community/api/forum/Season; 73: aastore 74: dup 75: iconst_3 76: getstatic #15 // Field Winter:Lcom/lglg/community/api/forum/Season; 79: aastore 80: putstatic #1 // Field $VALUES:[Lcom/lglg/community/api/forum/Season; 83: return}

定义的枚举类其实本质还是Class,继承自java.lang.Enum.定义的枚举变量本质是当前类的公开、静态,final的当前类做属性。

枚举中的基本方法

Java 枚举默认继承了 java.lang.Enum 类,包含以下常用方法:

方法名描述name返回枚举常量的名称(定义时的字符串)。ordinal返回枚举常量的序号,从 0 开始。values返回包含所有枚举常量的数组。valueOf(String name)根据名称返回对应的枚举常量,名称必须匹配。Season abc = Season.valueOf("Summer");System.out.println(abc);for (Season value : Season.values) { System.out.println("name:" + value.name); System.out.println("ordinal:" + value.ordinal); System.out.println("declaringClass:" + value.getDeclaringClass); System.out.println("describeConstable:" + value.describeConstable.get);}

输出:

Summername:Springordinal:0declaringClass:class com.fs.community.api.forum.SeasondescribeConstable:EnumDesc[Season.Spring]name:Summerordinal:1declaringClass:class com.fs.community.api.forum.SeasondescribeConstable:EnumDesc[Season.Summer]name:Autumnordinal:2declaringClass:class com.fs.community.api.forum.SeasondescribeConstable:EnumDesc[Season.Autumn]name:Winterordinal:3declaringClass:class com.fs.community.api.forum.SeasondescribeConstable:EnumDesc[Season.Winter]

枚举中添加属性

@RequiredArgsConstructorpublic enum SignalLight { /** * 红灯 */ RED(1), /** * 绿灯 */ GREEN(2), /** * 黄灯 */ YELLOW(3); private final Integer code;}

枚举中添加方法

import lombok.Getter;import lombok.RequiredArgsConstructor;@RequiredArgsConstructor@Getterpublic enum SignalLight { RED(1), GREEN(2), YELLOW(3); private final Integer code; /** * 是否可通行 * @Description isPassable * @Author jay.li * @Time 2024/12/18 * @param code * @return boolean */ public static boolean isPassable(Integer code) { return GREEN.getCode.equals(code); } /** * 是否可通行 * @Description isPassable * @Author jay.li * @Time 2024/12/18 * @return boolean */ public boolean isPassableInner(Integer code) { return GREEN.getCode.equals(this.code); }}

测试:

for (int i = 1; i

枚举中添加抽象方法

import java.util.Function.Function;public enum Operation { ADD { @Override Double apply(Double a, Double b, Function fun) { return fun.apply(a + b); } }, SUB { @Override Double apply(Double a, Double b, Function fun) { return fun.apply(a - b); } }, MUL { @Override Double apply(Double a, Double b, Function fun) { return fun.apply(a * b); } }, DIV { @Override Double apply(Double a, Double b, Function fun) { return fun.apply(a / b); } }, MOD { @Override Double apply(Double a, Double b, Function fun) { return fun.apply(a % b); } }; abstract Double apply(Double a, Double b, Function fun);}

枚举继承接口

import lombok.Getter;import lombok.RequiredArgsConstructor;interface OrderInterface { void exec;}@Getter@RequiredArgsConstructorpublic enum OrderStatus implements OrderInterface { Pending(1, "创建成功") { @Override public void exec { System.out.println("创建订单成功,给用户发送邮件通知"); } }, Paid(2, "已支付") { @Override public void exec { System.out.println("订单已支付,给用户发送邮件,告知发货计划"); } }, Cancelled(3, "已取消") { @Override public void exec { System.out.println("订单已取消,给对应的客服发送邮件通知,订单取消,做后续处理"); } }; private final Integer status; private final String desc;}// output创建订单成功,给用户发送邮件通知订单已支付,给用户发送邮件,告知发货计划订单已取消,给对应的客服发送邮件通知,订单取消,做后续处理

不同枚举常量实现了相同接口,但逻辑行为可以各不相同。

比如还可以使用枚举和接口实现状态机的转换,再比如实现多态行为等。

interface StateInterface { State next;}public enum State implements StateInterface { INIT { @Override public State next { return OPEN; } }, OPEN { @Override public State next { return null; } }, SHIPPED { @Override public State next { return DELIVERED; } }, DELIVERED { @Override public State next { return this; // 最终状态,保持不变 } interface DocumentFormatInterface { String format(String content);}public enum DocumentFormat implements DocumentFormatInterface { HTML { @Override public String format(String content) { return "" + content + ""; } }, XML { @Override public String format(String content) { return "" + content + ""; } }, JSON { @Override public String format(String content) { return "{\"content\": \"" + content + "\"}"; } }, TXT { @Override public String format(String content) { return content; } };}

枚举实现单利模式

线程安全:枚举在 Java 中的初始化是线程安全的,无需额外的同步控制。防止反射攻击:通过反射无法破坏枚举的单例特性。防止序列化攻击:枚举类自动实现了 Serializable,并保证反序列化后仍然是同一个实例。代码简洁:无需额外的代码管理单例逻辑public enum DBCon { INSTANCE; private Connection connection; DBCon { try { // 加载数据库驱动(根据实际情况替换) Class.forName("com.mysql.cj.jdbc.Driver"); // 初始化数据库连接(根据实际情况修改 URL、用户名和密码) String url = "jdbc:mysql://localhost:3306/testdb"; String username = "root"; String password = "password"; connection = DriverManager.getConnection(url, username, password); } catch (ClassNotFoundException | SQLException e) { throw new RuntimeException("Failed to initialize database connection.", e); } } public Connection getConnection { return connection; }}

EnumMap

是 Java 集合框架中的一个特殊实现,适用于以枚举类型为键的映射。它是一个非常高效的实现,因为它利用了枚举类型的有限性和固定顺序的特性。在一些需要高性能且以枚举为键的场景中,EnumMap 是首选。

EnumMap 的基本特点

1.键必须是枚举类型:EnumMap 的键只能是单一的枚举类型。

2.高效:基于枚举的自然顺序实现,使用数组作为底层结构,访问速度非常快。

3.内存使用优化:因为枚举的键是有限的,EnumMap 使用数组存储值,不需要哈希计算。

4.线程安全:EnumMap 本身不是线程安全的,需要在多线程环境下进行同步处理。

import lombok.AllArgsConstructor;import lombok.Data;import lombok.Getter;import lombok.RequiredArgsConstructor;import java.util.EnumMap;import java.util.Map;@RequiredArgsConstructor@Getterpublic enum Country { CN(1, "CN", "中国"), MO(2, "MO", "中国-澳门"), HK(3, "HK", "中国-香港"), TW(4, "TW", "中国-台湾"), US(5, "US", "美国"), UK(6, "UK", "英国"), DE(7, "DE", "德国"), JP(8, "JP", "日本"), AU(9, "AU", "澳大利亚"), RU(10, "RU", "俄罗斯") ; private final Integer id; private final String code; private final String desc; public static final Map MAP = initMap; private static Map initMap { EnumMap map = new EnumMap(Country.class); for (Country value : Country.values) { map.put(value, new Counties(value.getId, value.getCode, value.getDesc)); } return map; }}@Data@AllArgsConstructorclass Counties { private Integer id; private String code; private String desc;}// 测试输出 Counties counties = Country.MAP.get(Country.CN); System.out.println(counties); Country.MAP.forEach((k, v) -> { System.out.println("k:" + k); System.out.println("v:" + v); });Counties(id=1, code=CN, desc=中国)k:CNv:Counties(id=1, code=CN, desc=中国)k:MOv:Counties(id=2, code=MO, desc=中国-澳门)

来源:散文随风想一点号

相关推荐