ITEM 35: USE INSTANCE FIELDS INSTEAD OF ORDINALS
许多枚举自然地与一个 int 值关联。所有枚举都有一个序数方法,它返回每个枚举常量在其类型中的数值位置。您可能想从序数中派生一个关联的int值:
// Abuse of ordinal to derive an associated value - DON'T DO THIS
public enum Ensemble {
SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET, NONET, DECTET;
public int numberOfMusicians() { return ordinal() + 1; }
}
虽然这个 enum 可以工作,但它的维护是一个噩梦。如果常量被重新排序,numberOfMusicians 方法将崩溃。如果您想添加第二个与您已经使用过的 int 值相关联的枚举常量,那就不太可能了。例如,为 double quartet 添加一个常量可能很好,它像 octet 一样,由八个音乐家组成,但是没有办法做到这一点。
此外,如果不为所有中间的 int 值添加常量,就不能为 int 值添加常量。例如,假设您想添加一个表示 triple quartet (由12位音乐家组成)的常量。对于由11个音乐家组成的合奏没有标准术语,因此您必须为未使用的int值(11)添加一个虚拟常量。这样做是不优雅的。如果许多int values 未被使用,这是不切实际的。
幸运的是,这些问题有一个简单的解决方案。永远不要从枚举的序号派生与枚举相关的值,而是将它存储在一个实例字段中:
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; }
}
Enum规范对 ordinal 有这样的描述:“大多数程序员不需要使用这种方法。它是为基于枚举的通用数据结构(如 EnumSet 和 EnumMap)设计的。除非使用这个字符编写代码,否则最好完全避免使用序号方法。
网友评论