第二十二章 枚举

基本 enum 特性

创建 enum 时,编译器会为你生成一个相关的类,这个类继承自 Java.lang.Enum

valueOf() 是在 Enum 中定义的 static 方法,它根据给定的名字返回相应的 enum 实例,如果不存在给定名字的实例,将会抛出异常。

将静态类型导入用于 enum

使用 static import 能够将 enum 实例的标识符带入当前的命名空间,所以无需再用 enum 类型来修饰 enum 实例。

方法添加

除了不能继承自一个 enum 之外,我们基本上可以将 enum 看作一个常规的类。也就是说我们可以向 enum 中添加方法。enum 甚至可以有 main() 方法。

我们只能在 enum 定义的内部使用其构造器创建 enum 实例。一旦 enum 的定义结束,编译器就不允许我们再使用其构造器来创建任何实例了。

覆盖 enum 的方法

覆盖 toSring() 方法,给我们提供了另一种方式来为枚举实例生成不同的字符串描述信息。

values 方法的神秘之处

编译器创建的 enum 类都继承自 Enum 类,然而 Enum 类并没有 values() 方法。values() 是由编译器添加的 static 方法。编译器还为其添加了 valueOf() 方法。Enum 中的 valueOf() 方法需要两个参数,而这个新增的方法只需一个参数。

由于 values() 方法是由编译器插入到 enum 定义中的 static 方法,所以,如果你将 enum 实例向上转型为 Enum,那么 values() 方法就不可访问了。不过,在 Class 中有一个 getEnumConstants() 方法,所以即便 Enum 接口中没有 values() 方法,我们仍然可以通过 Class 对象取得所有 enum 实例。

enum Search {
HITHER, YON
} public class UpcastEnum {
public static void main(String[] args) {
Search[] vals = Search.values();
Enum e = Search.HITHER; // Upcast
// e.values(); // No values() in Enum
for (Enum en : e.getClass().getEnumConstants())
System.out.println(en);
}
}

实现而非继承

所有的 enum 都继承自 Java.lang.Enum 类。由于 Java 不支持多重继承,所以你的 enum 不能再继承其他类,然而,在我们创建一个新的 enum 时,可以同时实现一个或多个接口。

使用接口组织枚举

在一个接口的内部,创建实现该接口的枚举,以此将元素进行分组,可以达到将枚举元素分类组织的目的。

public interface Food {
enum Appetizer implements Food {
SALAD, SOUP, SPRING_ROLLS;
} enum MainCourse implements Food {
LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO;
} enum Dessert implements Food {
TIRAMISU, GELATO, BLACK_FOREST_CAKE, FRUIT, CREME_CARAMEL;
} enum Coffee implements Food {
BLACK_COFFEE, DECAF_COFFEE, ESPRESSO, LATTE, CAPPUCCINO, TEA, HERB_TEA;
}
}

使用 EnumSet 替代 Flags

ava SE5 引入 EnumSet,是为了通过 enum 创建一种替代品,以替代传统的基于 int 的“位标志”。EnumSet 的设计充分考虑到了速度因素。

使用 EnumMap

EnumMap 是一种特殊的 Map,它要求其中的键(key)必须来自一个 enum,由于 enum 本身的限制,所以 EnumMap 在内部可由数组实现。EnumMap 的速度很快。

常量特定方法

Java 的 enum 有一个非常有趣的特性,即它允许程序员为 enum 实例编写方法,从而为每个 enum 实例赋予各自不同的行为。要实现常量相关的方法,你需要为 enum 定义一个或多个 abstract 方法,然后为每个 enum 实例实现该抽象方法。

public enum OverrideConstantSpecific {
NUT, BOLT, WASHER {
@Override
void f() {
System.out.println("Overridden method");
}
};
void f() {
System.out.println("default behavior");
} public static void main(String[] args) {
for (OverrideConstantSpecific ocs : values()) {
System.out.print(ocs + ": ");
ocs.f();
}
}
}

使用 enum 的职责链

在职责链(Chain of Responsibility)设计模式中,程序员以多种不同的方式来解决一个问题,然后将它们链接在一起。当一个请求到来时,它遍历这个链,直到链中的某个解决方案能够处理该请求。

使用 enum 的状态机

枚举类型非常适合用来创建状态机。一个状态机可以具有有限个特定的状态,它通常根据输入,从一个状态转移到下一个状态,不过也可能存在瞬时状态(transient states),而一旦任务执行结束,状态机就会立刻离开瞬时状态。

多路分发

Java 只支持单路分发。也就是说,如果要执行的操作包含了不止一个类型未知的对象时,那么 Java 的动态绑定机制只能处理其中一个的类型。

最新文章

  1. CentOS 6.5安装 ASM lib
  2. duilib进阶教程 -- 各种控件的响应 (10)
  3. weblogic管理1——创建 和 删除一个domain
  4. 转: android studio 消除SDK更新时的“https://dl-ssl.google.com refused”错误
  5. C盘不能新建文件的问题解决办法
  6. jquery mobile展开项collapsible
  7. CodeForces 235C Cyclical Quest(后缀自动机)
  8. android 拍照注意问题
  9. Qt 富文本处理
  10. Celery 源码解析三: Task 对象的实现
  11. bat脚本:windows下一键启动zookeeper+kafka
  12. [转]微信小程序实现图片上传功能
  13. JS取出两个数组中的不同或相同元素
  14. iOS-省市区选择的实现
  15. mysql删除数据左右空格
  16. OpenFlow PacketOut消息机制
  17. JQuery中serialize()、serializeArray()和param()用法举例
  18. C#学习笔记(九):函数、代码查询和调试
  19. stenciljs 学习十三 @stencil/router 组件使用说明
  20. 【译】第九篇 SQL Server代理了解作业和安全

热门文章

  1. centos 7 安装相关环境
  2. BAT面试必问题系列:深入详解JVM 内存区域及内存溢出分析
  3. 8.docker的系统资源限制
  4. Java日期时间以及日期相互转换_java - JAVA
  5. Python3 install pip
  6. 去掉html中的标签
  7. [原创]Laravel 基于redis队列的解析
  8. compile and link C/CPP programs on Mac
  9. LTE系统时延及降低空口时延的4种方案
  10. SQL server 字段合并CAST(org_no AS VARCHAR(20))+CAST(page_no AS VARCHAR(20))+CAST(djlb_no AS VARCHAR(20)))