Java开关案例-默认与显式枚举

Java开关案例-默认与显式枚举,java,switch-statement,Java,Switch Statement,我正在使用Java6 假设我有一个有6个值的枚举,从A到F排序。大约有4个值是以相同的方式处理的。我可以这样写 switch (whichType) { case A: case B: case C: case D: return task(); case E: return someothertask(); case F: return anothersomeothertask(); } swit

我正在使用Java6

假设我有一个有6个值的枚举,从A到F排序。大约有4个值是以相同的方式处理的。我可以这样写

switch (whichType) {
    case A:
    case B:
    case C:
    case D:
        return task();
    case E:
        return someothertask();
    case F:
        return anothersomeothertask();
}
switch (whichType) {
    case E:
        return someothertask();
    case F:
        return anothersomeothertask();
    default:
        return task();
}
或者像这样

switch (whichType) {
    case A:
    case B:
    case C:
    case D:
        return task();
    case E:
        return someothertask();
    case F:
        return anothersomeothertask();
}
switch (whichType) {
    case E:
        return someothertask();
    case F:
        return anothersomeothertask();
    default:
        return task();
}
空值永远不会到达此开关

就简洁和清晰而言,第二种方法更好。就明确而言,我认为第一种方法更好

每种方法是否还有其他优点/缺点


而且,这个简单的问题有可能被重复,但我试过了,但在任何地方都找不到。如果搜索得不够好,我深表歉意。

假设有人向枚举添加了一个值

在我得到的一些代码中,有这样的构造:

switch(mediaType) {
    case typeA:
    case typeB:
    case typeC:
        DoGeneric();
        break;
    case TypeD:
        DoSpecial();
        break;
}

这样做的原因是,如果有人向枚举中添加了另一种可能性,那么它将不会编译,直到您查看了枚举的使用位置,并确定了在该点需要执行的操作。不可能漏掉一个,并且有一个难以追踪的bug。

好吧,关于可读性,我认为第二个可能不太清楚。例如,您的普通案例发生在您的特殊案例之后

然而,我在这里看到的真正问题是,这两段代码实际上并不等同。在第一种情况下,您有六个显式情况。在第二种情况下,您有两个显式情况和一个默认情况。这意味着,如果您的代码出现了某种错误,您收到了一个意想不到的案例,那么默认案例仍将在第二个案例中执行(并且
task()
仍将运行)。因此,这与您的第一个代码有根本的不同


除此之外(决定哪个switch语句是正确的),我要说的是,坚持读对你来说最好的语句。我个人喜欢第一个(因为它是明确的,如果需要的话,它为默认情况留出了空间),但您必须根据自己的偏好或公司/团队的开发标准来决定。如果枚举永远绝对固定在六个值上,那么这两个都可以。否则,请考虑枚举的第七个值可能是多少。如果E和F是与此
开关
逻辑相关的唯一两个可能的异常值,并且任何其他值都将与A到D落在同一个区间内,则继续使用
默认值
。否则,每个值都有一个
案例更安全。

如果您正在编写一些业务场景,并且您希望代码在未来几年继续存在并(由其他人)维护,请使用选项1。选项2没有什么错,它简短而清晰,但当谈到可维护性时,我认为选项1获胜——特别是当案例与某些业务逻辑相关时。维护工程师阅读它会容易得多。

我倾向于使用默认值来捕获初始实现后添加的新枚举。这不会产生编译时错误,我更喜欢这样,但它通常不会通过冒烟测试

switch (whichType) {
    case A:
    case B:
    case C:
    case D:
        return task();
    case E:
        return someothertask();
    case F:
        return anothersomeothertask();
    default:
        throw new IllegalArgumentException("Encountered unknown type: " + whichType.name());
}

将一个抽象方法添加到EnUM类中?仅用于记录:您可以在代码顶部>中间>或在代码>开关> <代码>中的任何地方放置<代码>默认节;它不一定要在底部。@ChrisJester-Young但一些静态代码分析器禁止将默认值放在非底部位置。@mjafari:如果他们有这样的任意要求,那不是我的错。:-P我知道有些人(比如在他们的工具中写入此类限制的人)认为非底部
default
子句是糟糕的风格,但我不同意,如果它能让代码更清晰,我会毫不犹豫地使用它。嗯。。。有人添加
typeE
@Stephen C:根据语言的不同,可能会编译这些代码(我不是用Java开发的)。但是通过这种方式,您的代码样式工具可以使用它,而使用
default
则无法判断它是否被遗忘。