Switch/case是在大多数命令式编程语言中实现的通用控制结构。Switch被认为比if/else系列更具可读性。
这是一个简单的例子:
switch (c) { |
以下是此代码中的主要问题列表:
- int类型的字符号(1,2,3)和执行的代码之间的关系并不明显。
- 如果其中一个值(例如2)不再受支持,并且此switch未相应更新,则它将永远包含未使用的代码。
- 如果引入了新的可能值c(例如4)并且Swtich没有相应更新,则代码可能会在运行时抛出UnsupportedOperationException,而不会在编译时发生任何通知。
- 这种Switch结构往往在代码中被重复多次,使问题2和3更加复杂。
使用int变量可以简单解决:
private static int ONE = 1; |
那么代码成为下面这样:
switch (c) { |
(显然在现实生活中,常量的名称必须是自描述的)这个片段更具可读性,但所有其他缺点仍然相关。
枚举Enum
进一步改进初始代码片段的尝试是使用2004年版本5中引入Java语言的枚举。
让我们定义以下枚举:
enum Action {ONE, TWO, THREE} |
现在,Switch代码段会略有变化:
Action a = ... |
这段代码更好一点:如果从枚举Action中删除了其中一个元素,它将产生编译错误。 但是,如果向枚举Action添加了其他元素,则不会导致编译错误 。 在这种情况下,某些IDE或静态代码分析工具可能会产生警告,但是谁会关注警告你?幸运的是,枚举可以声明必须由每个元素实现的抽象方法:
enum Action { |
现在switch语句可以替换为单行:
Action a = ... |
该解决方案没有上面列举的任何缺点:
- 它是可读的。该方法被“附加”到枚举元素; 如果方法含义不清楚,可以根据需要编写尽可能多的javadoc。调用方法的代码是微不足道的:什么可以比方法调用更简单?
- 如果不删除实现,就无法删除 枚举常量,因此如果某些功能不再相关,则不会保留未使用的代码。
- 如果没有实现方法action(),则无法添加新的 枚举元素。没有实现的代码会无法编译。
- 如果需要多个操作,则可以在枚举中实现所有操作 。正如我们已经提到的,调用特定函数的代码是微不足道的,所以现在没有代码重复。