前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「JAVA」以周的案例引出Java 枚举,以单例设计模式实践Java 枚举

「JAVA」以周的案例引出Java 枚举,以单例设计模式实践Java 枚举

作者头像
老夫编程说
修改2020-06-17 21:19:52
5520
修改2020-06-17 21:19:52
举报
文章被收录于专栏:Java 温故知新
Java面向对象之枚举——enum
Java面向对象之枚举——enum

引出枚举

首先来考虑这样一个需求:判断一个员工(Employee)在一周的哪一天休息。

解决方案:定义一个类Weekday来表示周1到周日,在类中分别使用7个常量来表示周1到周日,代码如下:

代码语言:javascript
复制
public class Employee {

    // 休息日
    private int restDay;
	
    public void setRestDay(int restDay) {
	    this.restDay = restDay;
    }
	
    public int getRestDay() {
	    return restDay;
    }
  
    public void isRestDay() {
  	    if (restDay == 6 || restDay == 7) {
            System.out.println("今天是休息日");
        } else {
    	    System.out.println("今天不是休息日");
        }
    }
}

public class WeekDay {
    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;
}

运行案例:

代码语言:javascript
复制
public static void main(String[] args) {
    Employee employee = new Employee();
    employee.setRestDay(WeekDay.SUNDAY);
    employee.isRestDay();
}

此时,上述的代码示例很清楚的解决了业务需求,引入的Weekday类很好的表示了从周一到周日。但是也存在一些问题,因为在Employee中的restDay的类型是int类型,我们依然可以随意设置restDay的值,代码并不健壮,依然没有解决数据类型不安全的问题,任然有改进的空间。

为了解决数据类型不安全的问题,可以在WeekDay中引入私有构造器,防止WeekDay被除自身以外的其他对象实例化,然后可以将WeekDay作为休息日的数据类型,很好的解决了数据类型不安全的问题,同时,也可以将休息日的个数固定下来。改造后的代码如下:

代码语言:javascript
复制
public class Employee {

    // 休息日
    private WeekDay restDay;
	
    public void setRestDay(WeekDay restDay) {
	   this.restDay = restDay;
    }
	
    public WeekDay getRestDay() {
	   return restDay;
    }
  
    public void isRestDay() {
        if (restDay == WeekDay.SATURDAY || restDay == WeekDay.SUNDAY) {
            System.out.println("今天是休息日");
        } else {
    	    System.out.println("今天不是休息日");
        }
   }
}
代码语言:javascript
复制
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();
}

运行案例:

代码语言:javascript
复制
public static void main(String[] args) {
    Employee employee = new Employee();
    employee.setRestDay(WeekDay.SUNDAY);
    employee.isRestDay();
}

到这里,不仅业务需求明确,数据类型安全的问题也解决了。

Java 枚举

从Java 5 开始,提供了一种新的数据类型,枚举。和接口一样,枚举是一个特殊的类,其实质上就是数量固定的多个常量对象的集合。枚举主要用来表示固定的事务类型。

枚举语法定义格式:常量之间使用英文状态下的“,”分隔,最后一个常量之后必须要用“;”结尾。

代码语言:javascript
复制
[修饰符] enum 枚举类名
{

    常量A,常量B,常量C;}

在上述案例中的WeekDay类用枚举来重写就是这样的:

代码语言:javascript
复制
enum  WeekDay {
    MONDAY,TUESDAY,WEDNESDAY,THURSDAY ,FRIDAY,SATURDAY,SUNDAY;
}

在开发中自定义的枚举类,在底层都是直接继承于java.lang.Enum类的,Enum类是所有枚举的父类。看下图会有一个更直观的感受:

底层的枚举类
底层的枚举类

枚举特点:

  • 枚举的直接父类是java.lang.Enum,但和java.lang.Object一样,枚举都不会显式地继承Enum。
  • 枚举就相当于一个类,可以定义构造方法、成员变量、普通方法和抽象方法。
  • 拥有默认的私有构造方法,即使不写访问权限也是private,因为枚举在底层没有无参数构造器的。
  • 枚举中的每个常量都是全局的,每个常量都是一个实例,且因为常量个数是固定的有限个的,所以实例个数也是固定的,且枚举类不能使用new关键字。
  • 枚举实例必须位于枚举结构体中的最开始部分,枚举实例列表的最后必须要有分号与其他成员相分隔。
  • 枚举实例后有花括号时,该实例是枚举类的匿名内部类对象。

枚举的使用

1.枚举中的常量都是全局公共的静态常量,可以直接使用枚举类名调用。

代码语言:javascript
复制
Weekday day = Weekday.SATURDAY;

2.因为java.lang.Enum类是所有枚举类的父类,所以所有的枚举对象可以调用Enum类中的方法。

代码语言:javascript
复制
String name = 枚举对象.name();   // 返回枚举对象的常量名称
int ordinal = 枚举对象.ordinal();  // 返回枚举对象的序号,从0开始.
String str = 枚举对象.toString();  // 返回 枚举对象的常量名称

3.JVM为枚举类生成的静态方法:

代码语言:javascript
复制
1.枚举类型[] values();
Weekday[] ws = Weekday.values(); 
// 返回当前枚举类型所有的常量,使用一个数组封装起来.

2.枚举类型 valueof(String name);
Weekday day = Weekday.valueOf("MONDAY"); 
//  把一个指定名称字符串转换为当前枚举类中同名的常量.

4.从Java 5开始switch也支持操作枚举类型。虽然switch只支持int类型,但因为支持枚举时在底层使用的枚举常量的ordinal,而ordinal的类型依然是int类型。所以也可以说switch是在间接支持枚举。

switch支持枚举
switch支持枚举

枚举的单例模式

在<<effective java>>书中提到,建议使用枚举类做单例模式,能够很好的保护代码隐私,即使使用反射也不能创建对象。通过以下的两种代码对比,能够很直观的展现枚举实现的单例模式:

未使用枚举的单例模式
未使用枚举的单例模式
使用枚举的单例模式
使用枚举的单例模式

完结,老夫虽不正经,但老夫一身的才华!关注我,获取更多编程、科技知识。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老夫不正经 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引出枚举
  • Java 枚举
    • 枚举特点:
      • 枚举的使用:
      • 枚举的单例模式
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档