既然有了常量类为何还需要用枚举,时常思考枚举的意义。
应用场景:
对于在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方法。
网友评论