枚举类型 enum

枚举类型 enum

枚举类型是java 5 的新特性,即 enum 关键字,它使我们在需要群组并使用枚举类型集时,可以很方便的处理.在此之前,你需要创建一个整型常量集,必须要了解很多细节并需要格外仔细,以正确的产生enum的效果.

 1. 在java 5 以前如何创建一个常量类来表示星期,代码如下
//表示雇员哪一天休息的类
public class Employee{
    private int restDay;//表示休息日
    public int getRestDay() {
        return restDay;
    }
    public void setRestDay(int restDay) {
        this.restDay = restDay;
    }
}
//测试代码如下:
 public static void main(String[] args) {
        Employee e = new Employee();
        e.setRestDay(2);
        int restDay = e.getRestDay();
        if (restDay == 6 || restDay == 7){
            System.out.println("周末休息");
        } else {
            System.out.println("周一到周五休息");
        }
 }
//输出结果: 
        周一到周五休息

以上代码存在的问题:
用 int 类型做星期几存在的问题如下:
1. 类型不安全,完全可以设置 非 (1 - 7)之间的数字
2. 业务含义不明确,设置的 1 表示周几?

2. 解决方案,使用七个常量来表示星期几的常量类,代码如下:
//表示星期几的常量类
public class Weekday {
    private Weekday(){} //为了防止外界创建对象,让构造方法私有化
    public static final Weekday MONDAY = new Weekday();
    public static final Weekday TUESDAY = new Weekday();
    public static final Weekday WEDNESDAY = new Weekday();
    public static final Weekday THURSDAY = new Weekday();
    public static final Weekday FRIDAY = new Weekday();
    public static final Weekday SATURDAY = new Weekday();
    public static final Weekday SUNDAY = new Weekday();
}
//员工周几休息
public class Employee{
    private Weekday restDay;//表示休息日
    public Weekday getRestDay() {
        return restDay;
    }
    public void setRestDay(Weekday restDay) {
        this.restDay = restDay;
    }
}
//测试方法
 public static void main(String[] args) {
        Employee e = new Employee();
        e.setRestDay(Weekday.SATURDAY);
        Weekday restDay = e.getRestDay();
        if (restDay == Weekday.SATURDAY || restDay == Weekday.SUNDAY){
            System.out.println("周末休息");
        } else {
            System.out.println("周一到周五休息");
        }
}
//输出结果 :
        周末休息

注意:
Weekday 类的构造方法一定要私有化,为了防止外界创建对象,我们只能调用Weekday中的常量,而不能随便创建对象.
这样就可以避免以上用 int 类型做星期几时存在的 2 个问题.
但是以上代码还是太过于复杂,下面通过枚举来进行优化

 3. 通过枚举来创建一个常量类
//编译前代码
public enum WeekDays {
    MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
}
//测试代码
public static void main(String[] args) {
        Employee e = new Employee();
        e.setRestDay(WeekDays.SATURDAY);
        WeekDays restDay = e.getRestDay();
        if (restDay == WeekDays.SATURDAY || restDay == WeekDays.SUNDAY){
            System.out.println("周末休息");
        } else {
            System.out.println("周一到周五休息");
        }
}

通过反编译可以看到编译后的 枚举类如下:

//编译后代码
public final class WeekDays extends Enum
{
    public static final WeekDays MONDAY;
    public static final WeekDays TUESDAY;
    public static final WeekDays WEDNESDAY;
    public static final WeekDays THURSDAY;
    public static final WeekDays FRIDAY;
    public static final WeekDays SATURDAY;
    public static final WeekDays SUNDAY;

    private static final WeekDays $VALUES[];

    public static WeekDays[] values()
    {
        return (WeekDays[])$VALUES.clone();
    }

    public static WeekDays valueOf(String name)
    {
        return (WeekDays)Enum.valueOf(WeekDays, name);
    }

    private WeekDays(String s, int i)
    {
        super(s, i);
    }

    static 
    {
        MONDAY = new WeekDays("MONDAY", 0);
        TUESDAY = new WeekDays("TUESDAY", 1);
        WEDNESDAY = new WeekDays("WEDNESDAY", 2);
        THURSDAY = new WeekDays("THURSDAY", 3);
        FRIDAY = new WeekDays("FRIDAY", 4);
        SATURDAY = new WeekDays("SATURDAY", 5);
        SUNDAY = new WeekDays("SUNDAY", 6);
        $VALUES = (new WeekDays[] {
            MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        });
    }
}

枚举的特点:
1. 枚举的直接父类是 java.lang.Enum,但是不能显示继承 Enum.
2. 枚举就相当于一个类,可以定义构造方法,成员变量,普通方法和抽象方法
3. 默认私有的构造方法,即使不写访问权限也是private修饰(假的构造器,底层是没有无参数构造器的).
4. 每个实例分别用一个全局常量表示,枚举类的对象是固定的,实例个数有限,不能使用new关键字.
5. 枚举实例必须位于枚举体中最开始部分,枚举实例列表的后面要有分号与其他成员相分隔.
6. 枚举实例后有花括号时,该实例是枚举类的匿名内部类对象,(看编译后的Class文件).
枚举的使用:

  1. 枚举中都是全局的公共的静态常量,可以直接使用枚举类名调用.
    WeekDays day = WeekDays.MONDAY;
  2. 因为java.lang.Enum类是所有枚举类的父类,所以所有的枚举对象可以调用Enum类中的方法.
    String name = 枚举对象.name(); //返回枚举对象的常量名称
    int ordinal = 枚举对象.ordinal(); //返回枚举对象的序号,从0 开始
    String str = 枚举对象.toString(); //返回枚举对象的常量名称
  3. 编译器生成的枚举类的静态方法
    枚举类型 [] values();
    Weekdays [] weekdays = Weekdays.values(); // 返回当前枚举类型所有的常量,使用一个数组封装起来.
    枚举类型 valueOf(String name);
    Weekdays day = Weekdays.valueOf(“MONDAY”); //把一个指定名称字符串转换为当前枚举类中同名的常量. 注意: 传的字符串一定要和枚举中的常量名大小写一致,否则就会报错.

  4. 从java5开始出现枚举,switch也支持操作枚举类型.

//编译前
 switch (WeekDays.MONDAY){
       case MONDAY: break;
       case TUESDAY: break;
       case WEDNESDAY: break;
 }
//编译后的class文件
switch (1..SwitchMap.WeekDays[WeekDays.MONDAY.ordinal()])
{
        case 1: // '\001'
        case 2: // '\002'
        case 3: // '\003'
        default:
            return;
}

说明: 底层会调用的是ordinal()方法,而ordinal()方法的返回值是int类型
总结 : switch只支持int类型,支持枚举是因为底层使用的枚举对象的ordinal()方法,而ordinal()方法的返回值是int类型.
switch支持byte,short,char 类型,是因为底层会自动进行拆箱和装箱操作,将类型提升为int类型.
从java7开始 switch支持string类型,也是因为底层在进行自动转换.

枚举的作用:
枚举主要用来表示事物固定的类型,

枚举的单例设计模式:
使用枚举创建单例很安全,即使使用反射也不能创建对象

//编译前
public enum Singleton{
    INSTANCE;
}
//编译后
final class Singleton extends Enum
{

    public static final Singleton INSTANCE;
    private static final Singleton $VALUES[];

    public static Singleton[] values()
    {
        return (Singleton[])$VALUES.clone();
    }

    public static Singleton valueOf(String name)
    {
        return (Singleton)Enum.valueOf(Singleton, name);
    }

    private Singleton(String s, int i)
    {
        super(s, i);
    }

    static 
    {
        INSTANCE = new Singleton("INSTANCE", 0);
        $VALUES = (new Singleton[] {
            INSTANCE
        });
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值