高效 Java 技巧之不滥用枚举的下标

字数540 大约花费2分钟

所有的枚举类型都有一个 ordinal 方法,将返回枚举值在枚举类中的位置。

1
2
3
4
5
6
// 滥用下标,将下标与枚举值的属性特征联系在一起,应当避免这样做 
public enum Ensemble {
SOLO, DUET, TRIO, QUARTET, QUINTET,
SEXTET, SEPTET, OCTET, NONET, DECTET;
public int numberOfMusicians() { return ordinal() + 1; }
}

Ensemble 这个枚举表示合奏,枚举值从独奏(SOLO)依次增加直到十重奏(DECTET),numberOfMusicians 表示演奏的数目,正好是下标值加 1。比如 SOLO 排在第一个,下标值为 0,而演奏数目正好是 1。这种方式非常取巧,但是可能给维护带来噩梦。如果给枚举值重新排序,numberOfMusicians 方法的返回值就不再正确。如果有一个新的枚举值对应的演奏数目和已有的枚举值一样,比如 double quartet(双重四重奏),和 OCTET 一样,也是 8 个演奏,就会造成问题。此外,如果有一个演奏数目与已有的并不连续,比如现在想在上面的枚举基础上加一个 triple quartet(三重四重奏),由于演奏数目是 12,要想增加这个枚举值,就得先加演奏数目为 9、10、11 的枚举值,而这本来很可能是完全不需要的。

永远不要将与枚举值有关的属性和它的下标相关联,而应该将属性值独立保存。

1
2
3
4
5
6
7
8
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),
SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8),
NONET(9), DECTET(10), TRIPLE_QUARTET(12);
private final int numberOfMusicians;
Ensemble(int size) { this.numberOfMusicians = size; }
public int numberOfMusicians() { return numberOfMusicians; }
}

实际上,在枚举的定义中,对 ordinal 这个方法进行了明确说明:

1
 大部分编程人员不会用到这个方法,它是被设计来用于基于枚举的数据结构:EnumSet 和 EnumMap。

所以,除非你在编写这样的数据结构,最好不好使用 ordinal 这个方法。

谈谈 IT 的文章均为原创或翻译(翻译会注明外文来源),转载请以链接形式标明本文地址: http://tantanit.com/java-enum-do-not-abuse-ordinal/

谈谈IT

欢迎关注官方微信公众号获取最新原创文章