枚举声明定义了一个包含固定实例集合的 final 类。每个
常量都是该类的实例;从概念上说,该类扩展
Enum<E>,其中枚举类型作为 E;任何用户定义的枚举都不能扩展其他类。
编译器提供 values() 和 valueOf(String),而 Enum 提供
名称、序号、比较和序列化规则。
接口与常量特定行为 #
枚举可以实现接口,实现可以由所有常量共享,也可以在常量特定的类体中提供。
java
enum Operation {
ADD { int apply(int a, int b) { return a + b; } },
SUBTRACT { int apply(int a, int b) { return a - b; } };
abstract int apply(int a, int b);
}每个常量特定类体都是编译器生成的匿名子类。因此,虚派发会选择对应的重写方法。外层枚举仍然是封闭集合,所以当策略在编译时已知时,这是一种有效的 Strategy 实现。如果扩展必须独立安装,应优先使用注入的接口实现。
常量特定类体可以实现枚举的抽象方法。当行为共享时,适合使用枚举级实现。除非生命周期确实应覆盖整个进程,否则不要在枚举常量中保存可变状态:枚举实例由定义它们的类加载器初始化一次。
身份、顺序与集合 #
枚举序列化会保留单例身份:反序列化按名称解析常量,而不是分配新实例。禁止使用 clone,也禁止通过反射构造枚举实例。使用 == 判断枚举身份,并避免持久化 ordinal(),因为插入或重新排列常量会改变它。只有当源代码级稳定性是明确契约时才持久化 name();对于长期保存的数据,外部代码字段更安全。
Enum.compareTo 按声明顺序排列常量。EnumSet 使用常量序号紧凑地表示集合,EnumMap 使用枚举键索引值。两者都要求使用一种枚举类型;当这一约束自然存在时,它们优于通用集合。
java
EnumSet<Operation> enabled = EnumSet.of(Operation.ADD);
EnumMap<Operation, String> labels = new EnumMap<>(Operation.class);
labels.put(Operation.ADD, "addition");
评论
在 GitHub 上阅读或评论(发表评论需要登录)