- 枚举的产生和应用场景
枚举是从jdk1.5开始诞生的。
在Enum出现之前,我们对于一些系统常量,一般是使用配置文件,或者自定义常量类、字典。大家各有各的方法和规则,Enum出现后,就从一定意义上规范了这类需求。比如:项目中需要常用的颜色常量:red,yellow,blue.常规做法,
定义常量类:
public class ConstantColor { public static final String RED = "red";// 红色 public static final String YELLOW = "yellow";// 黄色 public static final String BLUE = "blue";// 蓝色 public static void main(String[] args) { System.out.println("红色=" + ConstantColor.RED); System.out.println("红色=" + ConstantColor.YELLOW); System.out.println("红色=" + ConstantColor.BLUE); } } 如果需要进行键值对的存储,一般会通过map来操作: public class ColorMap { private static Map<String, String> Color_Map = new HashMap<>(); public static Map<String, String> getColorMap() { if (Color_Map.size() == 0) { Color_Map.put("red", "红色"); Color_Map.put("yellow", "黄色"); Color_Map.put("blue", "蓝色"); } return Color_Map; } public static void main(String[] args) { Map<String, String> colorMap = ColorMap.getColorMap(); Set<Entry<String, String>> entrySet = colorMap.entrySet(); for (Entry<String, String> entry : entrySet) { System.out.println("key=" + entry.getKey()); System.out.println("value=" + entry.getValue()); } } }
- 枚举源码扫读
java.lang.Enum类是从jdk1.5开始诞生的。
Enum是一个abstract修饰的抽象类,但是纵观源码,没有发现任意一个abstract修饰的抽象方法和抽象接口。只有一个protected修饰的构造方法:
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { ... /** * Sole constructor. Programmers cannot invoke this constructor. * It is for use by code emitted by the compiler in response to * enum type declarations. * * @param name - The name of this enum constant, which is the identifier * used to declare it. * @param ordinal - The ordinal of this enumeration constant (its position * in the enum declaration, where the initial constant is assigned * an ordinal of zero). */ //从注释上知道,这个构造方法,我们自己在写enum的时候,是不能直接使用这个构造方法的,在jkd编译期自动编译,具体后面我们自己做实验 protected Enum(String name, int ordinal) { this.name = name; this.ordinal = ordinal; } ...} Enum中声明了name(对象描述),ordinal(类似于数组下标,从0开始)两个变量,同时提供获取Enum元素和序列号的方法name(),ordinal(): public final String name() { return name; } public final int ordinal() { return ordinal; }
方法中是直接返回了name和ordinal,根本进行复制、取值操作?怎么实现的呢?猜测就是通过上面protected的构造方法,编译时候自动转载进入class文件的。这些源码是笔者认为比较关键的。 - 枚举使用
- 基本使用
我们创建枚举,编译器会自动继承java.lang.Enum。元素的定义必须在代码段的最开始,多个元素之间用因为逗号分隔;如果只是定义,则最后一个元素后面可以使用分号结束,或者不写。如果还有其他代码,则必须以分号结束
运行结果如下:public enum EnumTest2 { RED, YELLOW, BLACK;//因为后面还有代码,必须显示逗号结尾,必须在最前面实例化 public static void main(String[] args) { System.out.println(EnumTest2.RED.name()); System.out.println(EnumTest2.RED.ordinal()); } }
RED
0
这就满足我们常见的常量定义使用,在规范的同时,方便扩展。 - 扩展使用
基本使用不满足我们需求时候,需要进行扩展,下面是笔者工作中的总结。
输出结果:public enum ErrCodeEnum { IS_OK("系统正常处理", "0"), MSG_ERROR("消息结构异常", "1"), SPIDER_ERROR("视图像爬虫异常", "2"), BASE_ERROR("基础能力平台异常", "3"), DISTRIBUTED_ERROR("分布式存储异常", "4"), TMP_ERROR("临时存储空间异常", "5"),; private String name;// 错误信息描述 private String code;// 错误编码 // 只有一个默认的构方,自定义私有化构造方法 private ErrCodeEnum(String name, String code) { this.name = name; this.code = code; } /** * 定义普通方法,通过给定的序列号获取该元素 * @param ordinal 枚举元素的序列号 * @return 指定序列号的枚举元素 */ public static String getErrCodeByOrdinal(int ordinal){ ErrCodeEnum[] enumArr=ErrCodeEnum.values(); for(ErrCodeEnum errCode:enumArr){ if(errCode.ordinal()==ordinal){ return errCode.name(); } } return ""; } /** * 定义普通方法,通过code获取元素name * @param code code * @return 通过code获取name,如果有多个相同code,只会返回第一个code */ public static String getNameByCode(String code){ ErrCodeEnum[] enumArr=ErrCodeEnum.values(); for(ErrCodeEnum errCode:enumArr){ if(errCode.getCode().equals(code)){ return errCode.getName(); } } return ""; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public static void main(String[] args) { System.out.println(getErrCodeByOrdinal(0)); System.out.println(getNameByCode("1")); System.out.println(ErrCodeEnum.IS_OK.getCode()); System.out.println(ErrCodeEnum.IS_OK.getName()); } }
IS_OK
消息结构异常
0
系统正常处理