《Effective Java》解读第35条:用实例域代替序数
·
第35条:用实例域代替序数
不要依赖枚举的 ordinal() 方法来获取与枚举常量关联的数值,而应该显式地定义实例域来存储这个值。
背景
在 Java 枚举中,每个常量都有一个 ordinal() 方法,返回它在枚举声明中的位置(从 0 开始)。
public enum Ensemble {
SOLO, DUET, TRIO, QUARTET;
}
class Main {
public static void main(String[] args) {
System.out.println(Ensemble.SOLO.ordinal()); // 0
System.out.println(Ensemble.DUET.ordinal()); // 1
System.out.println(Ensemble.TRIO.ordinal()); // 2
System.out.println(Ensemble.QUARTET.ordinal()); // 3
}
}
有时候程序员会想用 ordinal() 来获取一个与枚举常量关联的数字(比如上面的例子中,SOLO 对应 1 个乐器,DUET 对应 2 个……),但这是一个非常危险且易出错的做法。
为什么不应该使用 ordinal()?
-
脆弱性:枚举常量的声明顺序一旦改变,ordinal() 的值就会变化,而依赖它的代码可能出错。例如,如果在 SOLO 前加一个新的常量,所有后续常量的序数都会改变。
-
可读性差:代码中使用 ordinal() 的数字含义不明确,很难维护。
-
不够灵活:有时你想关联的值并不是从 0 开始的连续整数,或者有间隔(比如 1, 2, 4, 8)。
正确做法:使用实例域
为枚举显式定义一个私有字段,通过构造函数赋值,并提供公共访问方法。
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3), QUARTET(4);
private final int numberOfMusicians;
Ensemble(int size) {
this.numberOfMusicians = size;
}
public int getNumberOfMusicians() {
return numberOfMusicians;
}
}
何时可以使用ordinal
Enum规范中谈及ordinal方法时写道:“大多数程序员都不需要这个方法。它是设计用于像EnumSet 和EnumMap这种基于枚举的通用数据结构的。”除非你在编写的是这种数据结构,否则最好完全避免使用orainal方法。
更多推荐




所有评论(0)