zoukankan      html  css  js  c++  java
  • enum一个最不像class的class

    enum一个最不像class的class
    java枚举类型是jdk5出现的.它的出现主要为了解决一些有特殊意义,已经确定的,长度不会改变的集合.

    //月份描述
    public class Month {
        //月份名称
        private final String name;
        //月份天数
        private final int days;
    
        //构造子,给出一个月份名称,默认天数31天
        private Month(String name) {
            this(name, 31);
        }
        //构造子,给出月份名称,月份天数
        private Month(String name, int days) {
            this.name = name;
            this.days = days;
        }
    
        /*
        * 创建12个月份
        * */
        public static final Month JAN = new Month("January");
        public static final Month FEB = new Month("February", 28);
        public static final Month MAR = new Month("March");
        public static final Month APR = new Month("April", 30);
        public static final Month MAY = new Month("May");
        public static final Month JUN = new Month("June", 30);
        public static final Month JUL = new Month("July");
        public static final Month AUG = new Month("August");
        public static final Month SEP = new Month("September", 30);
        public static final Month OCT = new Month("October");
        public static final Month NOV = new Month("November", 30);
        public static final Month DEC = new Month("December");
    
        //获取月份名称
        public String getName() {
            return name;
        }
    
        //获取月份值
        public int getDays() {
            return days;
        }
    }
    public class Main {
        public static void main(String[] args) {
            System.out.println(Month.JAN);//demo7.Month@1b6d3586
            System.out.println(Month.JAN.getName());//January
            System.out.println(Month.JAN.getDays());//31
        }
    }

    以上代码是创建了一个不可改变的月份表.内部实现就是一个在一个类中创建了12个实例对象.在客户端无需创建,直接获取没有月份的相关属性.以上写法在没有enum类型出现前,是最实用的写法.我们也可以看出

    在enum类中,只提供查询方法,不提供修改方法.

    在jdk1.5以后,创建enum类型就简单的多了.

    public enum  EnumMonth {
        JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC;
    }
    public class Main {
        public static void main(String[] args) {
            System.out.println(EnumMonth.APR);//APR
        }
    }

    这样声明一个只有12个月份的类是不是简单的多.而且我们可以看出.在客户端我们直接打印enum项打印的值,而不是地址值.那么这里边到底是怎么实现的呢?我们来看看反编译后的enum

    public final class EnumMonth extends Enum
    {
    
        public static final EnumMonth JAN;
        public static final EnumMonth FEB;
        public static final EnumMonth MAR;
        public static final EnumMonth APR;
        public static final EnumMonth MAY;
        public static final EnumMonth JUN;
        public static final EnumMonth JUL;
        public static final EnumMonth AUG;
        public static final EnumMonth SEP;
        public static final EnumMonth OCT;
        public static final EnumMonth NOV;
        public static final EnumMonth DEC;
        private static final EnumMonth $VALUES[];
    
        public static EnumMonth[] values()
        {
            return (EnumMonth[])$VALUES.clone();
        }
    
        public static EnumMonth valueOf(String name)
        {
            return (EnumMonth)Enum.valueOf(demo7/EnumMonth, name);
        }
    
        private EnumMonth(String s, int i)
        {
            super(s, i);
        }
    
        static 
        {
            JAN = new EnumMonth("JAN", 0);
            FEB = new EnumMonth("FEB", 1);
            MAR = new EnumMonth("MAR", 2);
            APR = new EnumMonth("APR", 3);
            MAY = new EnumMonth("MAY", 4);
            JUN = new EnumMonth("JUN", 5);
            JUL = new EnumMonth("JUL", 6);
            AUG = new EnumMonth("AUG", 7);
            SEP = new EnumMonth("SEP", 8);
            OCT = new EnumMonth("OCT", 9);
            NOV = new EnumMonth("NOV", 10);
            DEC = new EnumMonth("DEC", 11);
            $VALUES = (new EnumMonth[] {
                JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, 
                NOV, DEC
            });
        }
    }

    从这个class文件我们能看出

    EnumMonth继承自Enum.

    EnumMonth有一个私有的两个参数的构造函数.

    EnumMonth类中的枚举项也是自己通过实例化的构成的.

    接下来我们来看看他的两个方法 valueOf() 和values()

    public class Main {
        public static void main(String[] args) {
            System.out.println(EnumMonth.APR);//APR
            EnumMonth apr = EnumMonth.valueOf("APR");
            System.out.println(apr);//APR
            EnumMonth[] values = EnumMonth.values();//JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC,
            for (EnumMonth enumMonth : values){
                System.out.print(enumMonth+",");
            }
        }
    }

    这不是我们的重点,现在我们要找它的toString()方法,可以让枚举项直接打印出值的,肯定只有toString().前往父类Enum寻找

     所以现在可以得出结论.当我们创建一个枚举类时,实际上是有一个两个参数构造函数.默认传递的实参是我们的枚举项字符串和索引.

    那么,如果我们覆盖双参数的构造函数呢?

    public enum  DoubleEnumMonth {
        JAN("JAN",0), FEB("FEB",1), MAR("MAR",2);
        private DoubleEnumMonth(String a, int b) {
    
        }
    }
    public class Main {
        public static void main(String[] args) {
            System.out.println(DoubleEnumMonth.JAN);//JAN
        }
    }

    可以看出,我们虽然只声明了双参数的构造子,并没有声明属性,也没有this赋值,但是依然可以通过toString()的方式直接访问到属性值.那肯定是编译器帮我们调用了super(a,b);来看一下

    public final class DoubleEnumMonth extends Enum
    {
    
        public static final DoubleEnumMonth JAN;
        public static final DoubleEnumMonth FEB;
        public static final DoubleEnumMonth MAR;
        private static final DoubleEnumMonth $VALUES[];
    
        public static DoubleEnumMonth[] values()
        {
            return (DoubleEnumMonth[])$VALUES.clone();
        }
    
        public static DoubleEnumMonth valueOf(String name)
        {
            return (DoubleEnumMonth)Enum.valueOf(demo7/DoubleEnumMonth, name);
        }
    
        private DoubleEnumMonth(String s, int i, String a, int b)
        {
            super(s, i);
        }
    
        static 
        {
            JAN = new DoubleEnumMonth("JAN", 0, "JAN", 0);
            FEB = new DoubleEnumMonth("FEB", 1, "FEB", 1);
            MAR = new DoubleEnumMonth("MAR", 2, "MAR", 2);
            $VALUES = (new DoubleEnumMonth[] {
                JAN, FEB, MAR
            });
        }
    }

    这个结果,既有些意外之中,又意料之外.编译器,帮我们做了一个4个参数的构造函数.不用说前两个肯定还是name和index.至于后两个才是我们自己赋的值.

    最后总结下.java的enum类型,自1.5出现后,就是为了简化我们创建一个集合类的不可改变类的.

  • 相关阅读:
    矩阵十题(7)
    线段树成段更新 poj 3468 A Simple Problem with Integers
    线段树单点更新 hdu 2795 Billboard
    线段树成段更新 poj 2528 Mayor's posters
    矩阵十题(10)
    矩阵十题(8)
    矩阵十题(5)
    矩阵十题(6)
    矩阵十题(9)
    矩阵十题(4)
  • 原文地址:https://www.cnblogs.com/zumengjie/p/11592821.html
Copyright © 2011-2022 走看看