聊聊java中的枚举enum(源码扫读、日常使用)

  1. 枚举的产生和应用场景
    枚举是从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());
    		}
    	}
    }


    
    
    
    
  2. 枚举源码扫读
    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文件的。这些源码是笔者认为比较关键的。
    
    
    
    
  3. 枚举使用
  • 基本使用
    我们创建枚举,编译器会自动继承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
    系统正常处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值