java的枚举类,真的是个类

  今天对接第三方支付,我用枚举规定了几个支付方式和状态。有同事看到,问我为什么用枚举,交流中我发现他们对枚举主要有两个误解,今天记录一下。

  一,把枚举当成class,广义上讲枚举也是类,你肯定写过public class ...或者 public interface ...,那么interface是类吗?,当然是,只不过是特殊的类,class是最基础和原始的,同样public enum ...也是,它和class与interface在同一个位置,说明是同一个级别的,都是类,但是我们总说枚举类枚举类,却让一些同学产生了误解,因为一说到类,他就想到class,狭义上的类,所以我的标题叫枚举类型,用类型来形容对了,他们都是java的数据类型或对象类型。 

  理解了这个,那么再看enum时就明白了,它已经是一个新的数据类型了,他有自己道道,虽然和class很像,但是区别也有很多,作为一个特殊的类,和interface一样,它比class多了很多约束和特点,这些造就了它在某些方面的简洁性和安全性,如果说interface的设计是为了继承和多态,那么enum的存在为了什么?网上有一个使用很多的例子如下:

/*

*普通类型,使用关键class

*/

public class DayDemo {

    public static final int MONDAY =1;

    public static final int TUESDAY=2;

    public static final int WEDNESDAY=3;

    public static final int THURSDAY=4;

    public static final int FRIDAY=5;

    public static final int SATURDAY=6;

    public static final int SUNDAY=7;

}

 

//枚举类型,使用关键字enum
enum Day {
    MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

 

   对比一下就可以看到它的简洁性,它们两个效果是一样的,但enum的强类型又保证了它的安全性,所以有人用enum作为形参,来约束传值的正确性。但枚举有它的独特性,比如你不能像class那样用“=”来赋值,枚举类不能被继承等等。

  第二个误解,枚举里的常量和class里的是一样的,这个原于使用时如下写法

 public static void main(String[] args){
        //直接引用
        Day day =Day.MONDAY;
    }

Day.MONDAY返回的是一个Day对象而不是String对象,为什么?因为枚举常量也是当前枚举的实例对象,同样,网上也有反编译的结果说明,Day的反编译文件如下:

//反编译Day.class
final class Day extends Enum
{
    //编译器为我们添加的静态的values()方法
    public static Day[] values()
    {
        return (Day[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static Day valueOf(String s)
    {
        return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s);
    }
    //私有构造函数
    private Day(String s, int i)
    {
        super(s, i);
    }
     //前面定义的7种枚举实例
    public static final Day MONDAY;
    public static final Day TUESDAY;
    public static final Day WEDNESDAY;
    public static final Day THURSDAY;
    public static final Day FRIDAY;
    public static final Day SATURDAY;
    public static final Day SUNDAY;
    private static final Day $VALUES[];

    static 
    {    
        //实例化枚举实例
        MONDAY = new Day("MONDAY", 0);
        TUESDAY = new Day("TUESDAY", 1);
        WEDNESDAY = new Day("WEDNESDAY", 2);
        THURSDAY = new Day("THURSDAY", 3);
        FRIDAY = new Day("FRIDAY", 4);
        SATURDAY = new Day("SATURDAY", 5);
        SUNDAY = new Day("SUNDAY", 6);
        $VALUES = (new Day[] {
            MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        });
    }
}

注意最后这一部分,static代码块中的内容,当你使用enum时,jvm给我们默默的做了很多工作,Day默认就继承了Enum类,并帮你实现了其中的方法,最后的那部分内容就帮你把常量变成了实例了。

所以Day.MONDAY这么写是拿不到字符串的值的,拿到是对象,所以你还需要继续调用对象的方法,那么Day中有什么方法呢,肯定是有Enum的方法的,就是toString()或是name方法,这里就要涉及到Enum的源码了,有兴趣的同学可以自行查阅。

再多说一个:向enum类添加方法与自定义构造函数

public enum Day {
          MONDAY("星期一"),
          TUESDAY("星期二"),
          WEDNESDAY("星期三"),
          THURSDAY("星期四"),
          FRIDAY("星期五"),
          SATURDAY("星期六"),
          SUNDAY("星期日");//记住要用分号结束

         private String desc;//中文描述

           /**
           * 私有构造,防止被外部调用
          * @param desc
          */
          private Day2(String desc){
                this.desc=desc;
         }

           /**
           * 定义方法,返回描述,跟常规类的定义没区别
          * @return
           */
           public String getDesc(){
                  return desc;
           }

  解决了第二个误解,你就知道了,为什么每个常量后边括号里只有一个值呢,有人却写了两个呢,因为咱们的这个自定义的构造函数只有一个参数,而每个枚举常量又都是一个个实实在在的对象实例,所以后边的值就相当于在new实例,调用我们定义的构造函数,所以你要写两个需要再加一个成员变量并写一个两个参数的构造器。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值