枚举
枚举类型
枚举类型(Enumerated Type)很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中。而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常量的定义相似。不过相比较常量类型,枚举类型可以为申明的变量提供更大的取值范围。为了改进
// 定义一周七天的枚举类型
public enum WeekDay { Mon, Tue, Wed, Thu, Fri, Sat, Sun }
// 读取当天的信息
WeekDay today = readToday();
// 根据日期来选择进行活动
switch(today) {
Mon: do something; break;
Tue: do something; break;
Wed: do something; break;
Thu: do something; break;
Fri: do something; break;
Sat: play sports game; break;
Sun: have a rest; break;
}
最直接的益处就是扩大
public enum WeekDay {
Mon("Monday"),
Tue("Tuesday"),
Wed("Wednesday"),
Thu("Thursday"),
Fri("Friday"),
Sat("Saturday"),
Sun("Sunday");
private final String day;
private WeekDay(String day) {
this.day = day;
}
public static void printDay(int i) {
switch (i) {
case 1:
System.out.println(WeekDay.Mon);
break;
// ...
default:
System.out.println("wrong number!");
}
}
public String getDay() {
return day;
}
}
枚举值关联
我们可以创建如下的枚举类型:
public enum Element {
H("Hydrogen"),
HE("Helium"),
// ...
NE("Neon");
public final String label;
private Element(String label) {
this.label = label;
}
}
首先,我们注意到声明列表中的特殊语法。这就是枚举类型的构造函数被调用的方式。尽管对枚举类型使用
然后我们声明一个实例变量
- 首先,我们选择了标签标识符而不是名称。尽管成员字段名可以使用,但我们还是选择了
label ,以避免与预定义的Enum.name() 方法相混淆。 - 第二,我们的标签字段是
final 的。虽然枚举的字段不一定是finals 的,但在大多数情况下我们不希望我们的标签发生变化。本着枚举值是恒定的精神,这是有道理的。 - 最后,标签字段是
public 的,所以我们可以直接访问标签。
System.out.println(BE.label);
另一方面,该字段可以是私有的,用
assertSame(Element.LI, Element.valueOf("LI"));
然而,我们可能也想通过我们的标签字段来查询一个枚举值。要做到这一点,我们可以添加一个静态方法。
public static Element valueOfLabel(String label) {
for (Element e : values()) {
if (e.label.equals(label)) {
return e;
}
}
return null;
}
assertSame(Element.LI, Element.valueOfLabel("Lithium"));
为了提高值查询的效率,我们还可以添加如下的缓存:
public enum Element {
H("Hydrogen", 1, 1.008f),
HE("Helium", 2, 4.0026f),
// ...
NE("Neon", 10, 20.180f);
private static final Map<String, Element> BY_LABEL = new HashMap<>();
private static final Map<Integer, Element> BY_ATOMIC_NUMBER = new HashMap<>();
private static final Map<Float, Element> BY_ATOMIC_WEIGHT = new HashMap<>();
static {
for (Element e : values()) {
BY_LABEL.put(e.label, e);
BY_ATOMIC_NUMBER.put(e.atomicNumber, e);
BY_ATOMIC_WEIGHT.put(e.atomicWeight, e);
}
}
public final String label;
public final int atomicNumber;
public final float atomicWeight;
private Element(String label, int atomicNumber, float atomicWeight) {
this.label = label;
this.atomicNumber = atomicNumber;
this.atomicWeight = atomicWeight;
}
public static Element valueOfLabel(String label) {
return BY_LABEL.get(label);
}
public static Element valueOfAtomicNumber(int number) {
return BY_ATOMIC_NUMBER.get(number);
}
public static Element valueOfAtomicWeight(float weight) {
return BY_ATOMIC_WEIGHT.get(weight);
}
}