• 大话 java枚举


      说实话,本人之前对java的枚举并不是特别的了解,直到到了新公司,看到好多都在用枚举,渐渐的了解了。在这里我总结一下,查漏补缺吧。

    一、优点

    1)增强代码可读性。
    2)传递参数错误。
    3)去除equals两者判断:由于常量值地址唯一,使用枚举可以直接通过“==”进行两个值之间的对比,性能会有所提高。
    4)编译优势(与常量类相比):常量类编译时,常量被直接编译进二进制代码中,常量值在升级中变化后,需要重新编译引用常量的类,因为二进制代码中存放的是旧值。枚举类编译时,没有把常量值编译到代码中,即使常量值发生改变,也不会影响引用常量的类。
    5)修改优势(与常量类相比):枚举类编译后默认final class,不允许继承可防止被子类修改。常量类可被继承修改、增加字段等,易导致父类不兼容。
    6)枚举型可直接与数据库交互。
    7)Switch语句优势:使用int、String类型switch时,当出现参数不确定的情况,偶尔会出现越界的现象,这样我们就需要做容错操作(if条件筛选等),使用枚举,编译期间限定类型,不允许发生越界。

     

     二、创建

    这是一个最基本的枚举定义,我感觉有以下几个特点:

    1) 定义时,使用了关键字 enum ,而不是class,或者interface;使用了enum,相当于被 static(能静态调用),final(不能被重写)修饰;

    2) 枚举的成员一般大写,之间用逗号,末尾用封号;

    3) 枚举也需要构造方法、属性、setter方法、getter方法;

    4) 尽量避免使用java.lang.Enum中的已有属性,如name,ordinal。不然可能会混淆——下文涉及;

    5) 尽量避免使用ordinal属性判断枚举成员。因为ordinal属性返回成员的索引,如下代码MAN返回0,WOMAN返回1,但是只要你在枚举定义的时候,错乱了顺序,或者在枚举成员之前添加新的成员,都会导致ordinal的值发生变化。试想一个例子,假如没有code,你数据库中根据ordinal存入了男(索引0),女(索引1),但是后来随着开发的必要,你感觉应该加一个未知性别,所以你就不小心在MAN和WOMAN的之间加了UNKNOW(2,"未知")。最终是这样 MAN(1,“男”),UNKNOW(2,“未知”),WOMAN(0,“女”),这时WOMAN的ordinal值已经变为了2,不是1了,所以数据库发生脏数据了。所以为了避免发生意外,尽量避免使用,或者严格规定,添加枚举成员只能在后面追加,不能中间插入。

    6)构造方法,枚举的构造方法默认是private,而且是强制的;

    7)枚举值默认被public static final修饰;

    public enum SexEnum {
        //
        MAN(1, "男"),
    
        //
        WOMAN(0, "女");
    
        /**
         * 属性
         */
        private int code;
    
        private String desc;
    
        /**
         * 构造方法
         * @param code
         * @param desc
         */
        SexEnum(Integer code, String desc) {
            this.code = code;
            this.desc = desc;
        }
    
        /**
         * getter and setter
         * @return
         */
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        public String getDesc() {
            return desc;
        }
    
        public void setDesc(String desc) {
            this.desc = desc;
        }
    }

    三、API

       java里面的枚举自动继承了java.lang.Enum,由于java不能多继承,所以枚举不能再继承其他类了。这是java.lang.Enum的源码,我们看到它实现了Comparable接口,所以java里面的所有枚举都是可以进行比较的。其中有几个重要的方法:

    1)name():返回枚举成员的名称;toString就是返回name值。

    2)ordinal():返回枚举成员的索引;

    3)compareTo():根据ordinal的值比较大小;

      a<b,a.compareTo(b) = -1;

      a=b,a.compareTo(b) = 0;

      a>b,a.compareTo(b) = 1;

    4)valueOf():将一个字符串映射成枚举;不存在就转化异常。

    5)values():获取该枚举对象的所有枚举值。——该方法暂未找到出处。

    package java.lang;
    
    import java.io.Serializable;
    import java.io.IOException;
    import java.io.InvalidObjectException;
    import java.io.ObjectInputStream;
    import java.io.ObjectStreamException;
    
    public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
       
        private final String name;
    
        public final String name() {
            return name;
        }
    
        private final int ordinal;
    
        public final int ordinal() {
            return ordinal;
        }
    
        protected Enum(String name, int ordinal) {
            this.name = name;
            this.ordinal = ordinal;
        }
    
        
        public String toString() {
            return name;
        }
        public final boolean equals(Object other) {
            return this==other;
        }
        public final int hashCode() {
            return super.hashCode();
        }
        protected final Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
    
        
        public final int compareTo(E o) {
            Enum<?> other = (Enum<?>)o;
            Enum<E> self = this;
            if (self.getClass() != other.getClass() && self.getDeclaringClass() != other.getDeclaringClass())
                throw new ClassCastException();
            return self.ordinal - other.ordinal;
        }
    
        public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name) {
            T result = enumType.enumConstantDirectory().get(name);
            if (result != null)
                return result;
            if (name == null)
                throw new NullPointerException("Name is null");
            throw new IllegalArgumentException("No enum constant " + enumType.getCanonicalName() + "." + name);
        }
    
        protected final void finalize() { }
    }
    public class EnumTest {
        /**
         * name属性:返回枚举名称
         */
        @Test
        public void test_name(){
            //MAN
            System.out.println(SexEnum.MAN.name());
            //WOMAN
            System.out.println(SexEnum.WOMAN.name());
        }
    
        /**
         * ordinal属性:返回枚举索引
         */
        @Test
        public void test_ordinal(){
            //0
            System.out.println(SexEnum.MAN.ordinal());
            //1
            System.out.println(SexEnum.WOMAN.ordinal());
        }
    
        /**
         * compareTo():根据ordinal的值比较大小
         */
        @Test
        public void test_compareTo(){
            //-1
            System.out.println(SexEnum.MAN.compareTo(SexEnum.WOMAN));
            //1
            System.out.println(SexEnum.WOMAN.compareTo(SexEnum.MAN));
            //0
            System.out.println(SexEnum.MAN.compareTo(SexEnum.MAN));
        }
    
        /**
         * valueOf():将字符串映射为枚举
         */
        @Test
        public void test_valueOf(){
            //MAN
            System.out.println(SexEnum.valueOf("MAN"));
            //java.lang.IllegalArgumentException: No enum constant SexEnum.MAN123
            System.out.println(SexEnum.valueOf("MAN123"));
        }
    
        /**
         * values():获取该枚举对象的所有枚举值
         */
        @Test
        public void test_values(){
            SexEnum[] enums = SexEnum.values();
            for (SexEnum sexEnum:enums){
                //MAN
                //WOMAN
                System.out.println(sexEnum);
            }
        }
    
    }

       

    四、集合

      3.1、EnumMap

      因为HashMap是一种通过对key计算hashCode(),通过空间换时间的方式,直接定位到value所在的内部数组的索引,因此,查找效率非常高。如果作为key的对象是enum类型,那么,还可以使用Java集合库提供的一种EnumMap,它在内部以一个非常紧凑的数组存储value,并且根据enum类型的key直接定位到内部数组的索引,并不需要计算hashCode(),不但效率最高,而且没有额外的空间浪费。使用EnumMap的时候,我们总是用Map接口来引用它,因此,实际上把HashMap和EnumMap互换,在客户端看来没有任何区别。

      3.2、EnumSet

        同EnumSet

    @Test
    public void test_EnumMap(){
        Map<SexEnum,String> enumMap = new EnumMap<SexEnum, String>(SexEnum.class);
        enumMap.put(SexEnum.MAN,"这是一个男生");
        enumMap.put(SexEnum.WOMAN,"这是一个女生");
    }
    
    @Test
    public void test_EnumSet(){
        EnumSet enumSet = EnumSet.allOf(SexEnum.class);
    }

      EnumMap、EnumSet的更多资料请查看 java.util.EnumMap实战java.util.EnumSet实战

    在全栈的道路上,积极向上、成熟稳重、谦虚好学、怀着炽热的心向前方的走得更远。
  • 相关阅读:
    【Spark 深入学习 02】- 我是一个凶残的spark
    【Spark 深入学习 01】 Spark是什么鬼?
    【Big Data
    【Netty】通俗地讲,Netty 能做什么?
    【Jetty】Jetty 的工作原理以及与 Tomcat 的比较
    【Tomcat】Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析
    【Tomcat】Tomcat 系统架构与设计模式,第 1 部分: 工作原理
    【Tomcat】Servlet 工作原理解析
    【Tomcat】面向初级 Web 开发人员的 Tomcat
    【Big Data
  • 原文地址:https://www.cnblogs.com/DDgougou/p/13347994.html
Copyright © 2020-2023  润新知