java 使用枚举定义常量

假如有一笔业务需要审核,审核状态分:未审核,审核中,审核通过,审核不通过。我们在程序里是否可以直接这么写:

if(state==1){//1代表未操作

      //操作

}else{

     //......

}

将状态标识直接写在代码里面(硬编码),只图一时方便,却是后患无穷,如果有一天你需要修改状态标识,用0代表未审核而不是1,你不得不将所有与该标识相关的代码都找出来一个个改,另外,在编码过程中,标识输入错误的概率是比较高的,一不小心把0输入成了10,虽然不会提示任何编译错误,但运行结果将是出乎人的意料的。

于是我们很快想到可以用常量代替:

public static final int UNAUDIT = 0;

相关判断代码则是:

if(state==CONSTANT.UNAUDIT){

      //操作

}else{

      //......

}

这段代码比硬编码更加健壮容易维护,但是仍然有不足之处。

1、UNAUDIT是编译期常量,如果其值被改变,那么使用方需要重新编译。

2、没有简便的方法获取标识代表的字符串描述。

于是我们用枚举类来代替常量。

public enum AuditState {

     UNAUDIT(1),

     AUDITING(2),

     AUDIT_SUCCESS(3),

     AUDIT_FAIL(4);

private final int statenum;

    AuditState(int statenum){

   this.statenum = statenum;

}

public int getStatenum() {

    return statenum;

}

}

调用如下:

if (state == AuditState.UNAUDIT.getStatenum()) {

    //AuditState.UNAUDIT.toString()获取字符串描述

System.out.println(

     AuditState.UNAUDIT.toString() + "标识是 "

    + AuditState.UNAUDIT.getStatenum());

} else {

   //......

}

枚举类还有更加强大的功能,如添加字段,方法,还可以对他进行遍历访问

一、分析 

常量的声明是每一个项目中不可或缺的,在Java1.5之前,我们只有两种方式的声明:类常量和接口常量。不过,在1.5版之后有了改进,即新增了一种常量声明方式,枚举常量。代码如下: 

enum Season{

    Spring,Summer,Autumn,Winter;

}

二、场景 

那么枚举常量与我们的经常使用的类常量和静态常量比有什么优势呢? 

1.枚举常量更简单 

先把Season枚举翻译成接口,代码如下: 

interface Season{

    int Sprint = 0;

    int Summer = 1;

    int Autumn = 2;

    int Winter = 3;

}

枚举只需要定义每个枚举项,不需要定义枚举值,而接口常量(或类常量)则必须定义值,否则编译通不过;两个引用的方式相同(都是“类名.属性”,如Season.Sprint),但是枚举表示的是一个枚举项,字面含义是春天,而接口常量却是一个Int类型。 

2.枚举常量属于稳态型 

使用常量接口,我们得对输入值进行检查,确定是否越界,如果常量非常庞大,校验输入就是一件非常麻烦的事情,但这是一个不可逃避的过程。 

public void describe(int s){

    //s变量不能超越边界,校验条件

    if(s >= 0 && s <4){

        switch(s){

            case Season.Summer:

                System.out.println("Summer is very hot!");

                break;

            case Season.Winter:

                System.out.println("Winter is very cold!");

                break;

        …..

        }

    }

}

我们再来看看枚举常量是否能够避免校验问题,代码如下:

public void describe(Season s){

    switch(s){

        case Season.Summer:

            System.out.println("Summer is very hot!");

            break;

        case Season.Winter:

            System.out.println("Winter is very cold!");

            break;

        …...

    }

}

不用校验,已经限定了是Season枚举,所以只能是Season类的四个实例。这也是我们看重枚举的地方:在编译期间限定类型,不允许发生越界的情况。

3.枚举具有内置方法 

每个枚举都是java.lang.Enum的子类,该基类提供了诸如获得排序值的ordinal方法、compareTo比较方法等,大大简化了常量的访问。比如,列出所有枚举值: 

public static void main(String[] args){

    for(Season s:Season.values()){

        System.out.println(s);

    }

}

4.枚举可以自定义方法 

这一点似乎不是枚举的优点,类常量也可以有自己的方法,但关键是枚举常量不仅仅可以定义静态方法,还可以定义非静态方法,而且还能够从根本上杜绝常量类被实例化。比如我们在定义获取最舒服的季节,使用枚举的代码如下: 

enum Season{

    Spring,Summer,Autumn,Winter;

    //最舒服的季节

    public static Season getComfortableSeason(){

        return Spring;

    }

}

那如果是使用类常量如何实现呢?如下: 

class Season{

    public final static int Spring = 0;

    public final static int Summer = 1;

    public final static int Autumn = 2;

    public final static int Winter = 3;

    //最舒服的季节

    public static int getComfortableSeason(){

        return Spring;

    }

}

虽然枚举在很多方面都比接口常量和类常量好用,但是它有一点比不上接口常量和类常量的,就是继承,枚举类型是不能有继承的,也就是说一个枚举常量定义完毕后,除非修改重构,否则无法做扩展。 

三、建议 

在项目开发中,推荐使用枚举常量代替接口常量或类常量。 

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 32,610评论 18 399
  • 昨天在做besuper的小型交互游戏的时候,强默默走到我边上,然后看了一眼我的代码,又一如既往的开始喷我:你这写的...
    wuchaooooo阅读 3,860评论 2 0
  • 一 Java 枚举7常见种用法DK1.5引入了新的类型——枚举。在 Java 中它虽然算个“小”功能,却给我的开发...
    欢乐时光欢乐你我阅读 4,322评论 0 6
  • 我有故我疑,我疑故我思。 我思故我知,我知故我在。 万人从此生,转眼一覆灭。 世界无穷去,心中留君名。 绿园芳草尽...
    后夏夕颜心静如水阅读 2,047评论 0 4
  • 6/13作者讲述了自己对孤独的看法。他说,习惯了孤独的自我,习惯了个体与真实的自我不再有距离。人多的时候,是无暇顾...
    向日葵的笑脸红红的阅读 2,372评论 0 0

友情链接更多精彩内容