Effective Java笔记第五章枚举和注解
第二节用实例域代替序数
许多枚举天生就与一个单独的int值相关联。所有的枚举都有一个ordinal方法,他返回每个枚举常量在类型中的数字位置。下面是Enum类的部分源码:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
private final int ordinal;
public final int ordinal() {
return ordinal;
}
}
我们举个例子:
public enum Ensemble {
AA,BB,CC,DD,EE;
public int numberOfMusicians(){
return ordinal()+1;
}
}
public class Test {
public static void main(String[] args) {
for (Ensemble value : Ensemble.values()) {
System.out.println(value.ordinal()+":"+value.name());
}
for (Ensemble value : Ensemble.values()) {
System.out.println(value.numberOfMusicians()+":"+value.name());
}
}
}
输出:
0:AA
1:BB
2:CC
3:DD
4:EE
1:AA
2:BB
3:CC
4:DD
5:EE
这个枚举方法有很大的缺陷,如果常量进行重新排序,numberOfMusicians方法就会遭到破坏,如果再添加一个与已经用过的int值相关联的枚举常量,就没那么走运了。
对此我们有一种很简单的方法:永远不要根据枚举的序数导出与它关联的值,而是要将他保存在一个实例域中。
下面我们对上文的代码进行改造:
public enum EnsembleImprove {
AA(1),BB(2),CC(3),DD(4),EE(5);
private final int number;
EnsembleImprove(int number) {
this.number = number;
}
public int numberOfMusicians(){
return number;
}
}
Enum规范中谈到ordinal时这么写到:大多数程序员都不需要这个方法。它是设计成用于EnumSet和EnumMap这种基于枚举的通用数据结构。除非你在编写的是这种数据结构,否则最好完全避免使用ordinal方法。