关于java枚举和常量类

2021-01-18  本文已影响0人  haiyong6

既然有了常量类为何还需要用枚举,时常思考枚举的意义。

应用场景:

对于在java代码中出现的需要解释其意义的常量,通常不会直接用数字或符号去表示(不清晰,不利于业务理解与管理),而是需要建一个常量类声明一个常量来统一管理。
比如现在有四个状态,分别是待升级,正在升级,升级失败,升级完成,这些状态在项目中通常使用数字来表示,比如分别定义为-1,3,4,5

这种情况下,我们单独定义一个常量类来统一管理需要满足以下几个特征:
1.可读性,一眼看到就知道是什么状态,而不是空洞洞的数字
2.不可更改性,这些定义好的东西,绝对不能被代码随意更改,所以会使用static final来修饰
3.可以方便的拿到定义好的数字和文字描述
4.必要时候可以拿到所有属性有序遍历,但是不可被代码更改。

基于以上几个特征我们通常会这样新建一个常量类:

package com.ly.mp.ota.common;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

public class UpgradeRecordConstant {
    
    public static final String TOBE_UPGRADED = "-1";
    public static final String UPGRADING = "3";
    public static final String FAILURE = "4";
    public static final String SUCCESS = "5";
    private static final Map<String, String> upgradeRecordNameMap = new LinkedHashMap<String, String>();
    static {
        upgradeRecordNameMap.put(TOBE_UPGRADED, "待升级");
        upgradeRecordNameMap.put(UPGRADING, "正在升级");
        upgradeRecordNameMap.put(FAILURE, "升级失败");
        upgradeRecordNameMap.put(SUCCESS, "升级完成");
    }
    
    public static String getNameByStatus(String status) {
        return null == upgradeRecordNameMap.get(status) ? "" : upgradeRecordNameMap.get(status);
    }
    
    public static Map<String, String> getUpgradeRecordNameMap(){
        return Collections.unmodifiableMap(upgradeRecordNameMap);
    }
    
    public static void main(String[] args) {
        System.out.println(UpgradeRecordConstant.getNameByStatus(UpgradeRecordConstant.FAILURE));
        System.out.println(UpgradeRecordConstant.FAILURE);
        System.out.println(UpgradeRecordConstant.getUpgradeRecordNameMap());
    }
}

上面代码中声明的几个状态都用static final修饰,所以不能被再次赋值,保证了常量的安全性,声明一个private static final类型的有序的LinkedHashMap,在初始化代码的时候赋值,并提供getNameByStatus方法获取此LinkedHashMap中的属性值,提供getUpgradeRecordNameMap方法来可以直接获取此map,Collections.unmodifiableMap来保证此map不可更改。运行main测试方法遍历结果如下:

升级失败
4
{-1=待升级, 3=正在升级, 4=升级失败, 5=升级完成}

如此,可以用类.属性直接拿到状态值,用getNameByStatus方法来获取值描述。

可以看到如果用常量类实现这些还是需要写一些代码的,所以在jdk1.5之后,java出现了枚举,它的出现就是为了让类似我们这种需求更加简单直观。

下面用枚举实现同样的功能:

package com.ly.mp.ota.common;

public enum UpgradeRecordStatus {
    
    TOBE_UPGRADED("待升级", "-1"),
    UPGRADING("正在升级", "3"),
    FAILURE("升级失败", "4"),
    SUCCESS("升级完成", "5");
    
    private String name;
    private String status;
    
    private UpgradeRecordStatus(String name, String status) {
        this.name = name;
        this.status = status;
    }

    public String getStatus() {
        return status;
    }
    
    public String getName() {
        return name;
    }
    public static void main(String[] args) {
        System.out.println(UpgradeRecordStatus.FAILURE.getName());
        System.out.println(UpgradeRecordStatus.FAILURE.getStatus());
        UpgradeRecordStatus[] arr = UpgradeRecordStatus.values();
        for(UpgradeRecordStatus s : arr) {
            System.out.println(s.getName() + " " + s.getStatus());
        }
    }
}

运行main方法结果如下:

升级失败
4
待升级 -1
正在升级 3
升级失败 4
升级完成 5

以上代码可以看出,用枚举实现同样的功能,代码量更少,枚举是专门为这样的场景设计,扩展性也比用常量好的多,现在只是id和name这两个属性,如果想要更多,枚举也只是在后面的构造方法里加多几个就可以了,而常用量可能要写更多的map才行。

枚举是已经继承了java.lang.Enum类的,所以不可再继承其他类,除此之外,他通常拥有普通java类的特点:可以有自己的成员变量,成员方法,静态方法、静态变量等,也能实现其他的接口,所以也许有人会问那枚举可以有set方法吗?从语法上是没有问题的,可以设置set方法来改变变量的值,但是通常不会这样做,因为毕竟有枚举的意义就是要保证每个属性都是常量,不可被更改的,所以在实际运用中最好不要设置set方法。

上一篇 下一篇

猜你喜欢

热点阅读