一、为什么需要枚举
举个例子,生物界性别分“雄性”、“雌性”和“中性”,将其定义为静态常量:
public class Gender{
public static final int Male = 1;
public static final int Female = 2;
public static final int Neutral = 3;
}
对于这种单值类型的静态常量定义,本身也没错,主要是在使用的地方没有一个明确性的约束而已,比如这里的 judgeGender 方法的本意是传入 Gender 的三种静态常量之一,但由于没有类型上的约束,因此传入任意一个 int 值都是可以的,编译器也不会提出任何警告。
void judgeGender(int code){}
但是在枚举类型出现之后,上面这种情况就可以用枚举严谨地去约束,比如用枚举去定义性别就非常简洁了:
public enum Gender {
Male, Female, Neutral
}
而且主要是在用枚举的地方会有更强的类型约束。如下入参类型就会受到明确的类型约束,一旦传入无效值,编译器就会帮检查,从而规避潜在问题。除此之外,枚举在扩展性方面比普通常量更方便、也更优雅。
//入参就限定了类型
void judgeGender(Gender gender){}
综上,枚举的意义:
1️⃣封装有限的变化,提高代码维护性,确保变量合法。
如果利用 int 类型表示星期一到星期日的话,就要判断输入 int 变量不在 1-7 的范围内的情况。
2️⃣代码更优雅,提高代码可读性。一个复制的程序里面,可能要用到成百上千的静态常量,如果全写在一个文件里面,容易造成命名混淆,程序读起来也比较麻烦。
二、单值枚举
定义一个性别枚举:
public enum Gender {
Male, Female, Neutral
}
枚举的所有基本用法:
public class judgeGender {
public static void main(String[] args) {
for (Gender genderType : Gender.values()) {
System.out.println(genderType);
}
Gender male = Gender.Male;
Gender female = Gender.Female;
Gender neutral = Gender.Neutral;
System.out.println(male.ordinal());//0
System.out.println(female.ordinal());//1
System.out.println(neutral.ordinal());//2
System.out.println(male.name());//Male
System.out.println(female.name());//Female
System.out.println(neutral.name());//Neutral
System.out.println(male.compareTo(male));//0
System.out.println(male.compareTo(female));//-1
System.out.println(female.compareTo(neutral));//-1
System.out.println(Gender.valueOf("Male"));//Male
System.out.println(Gender.valueOf("Female"));//Female
System.out.println(Gender.valueOf("Neutral"));//Neutral
Gender gender = Gender.Male;
switch (gender) {
case Male:
System.out.println("男");
break;
case Female:
System.out.println("女");
break;
case Neutral:
System.out.println("中性");
break;
}//男
}
}
三、多值枚举
上面展示的枚举例子非常简单,仅仅是单值的情形,而实际项目中用枚举往往是多值用法。扩充一下上面的 Gender 枚举,在里面加入 【说明 – 编码】的对应关系,这也是实际项目中常用的用法。可以在枚举里自定义各种属性、构造函数、甚至各种方法:
public enum GenterType {
Male("男", "01"),
Female("女", "02"),
Neutral("中性", "03"),
;
//自定义属性
private final String explain;
private final String code;
public String getExplain() {
return explain;
}
public String getCode() {
return code;
}
//自定义构造函数
GenterType(String explain, String code) {
this.explain = explain;
this.code = code;
}
}
从上述代码可知,在 enum 枚举类中完全可以像在普通 Class 里一样声明属性、构造函数以及成员方法。
四、专门用于枚举的集合类
一般习惯于使用诸如:HashMap 和 HashSet 等集合来盛放元素。而对于枚举,有专门的集合类: EnumSet 和 EnumMap
1️⃣EnumSet
EnumSet 是专门为盛放枚举类型所设计的 Set 类型。
2️⃣EnumMap
EnumMap 则是用来专门盛放枚举类型为 key 的 Map 类型。