什么是好的 "unreachable" 开关错误?

What is a good "unreachable" Error for switches?

Eclipse 强制我对任何 switch 使用 default 案例,包括那些列出所有声明的 enum 值的案例,据称是因为语言规范 [1]。这是不幸的,因为并行开发项目的 Android Studio 没有,并且自然会警告我所有 switches,如果 enum 被更改,它们将变得不完整。虽然我更喜欢后一种行为,因为前者使 enum 更改实际上 更多 容易出错(请参见下面的示例),但我无法选择,所以我需要找到对两者都正确的方法。我想如果代码中有一个地方在任何情况下都应该保持无法访问,但仍然不能删除该行,那么抛出 Error 似乎是自然而然的事情。但是哪一个,是否有针对这种情况的普遍接受的子类(可能扩展到其他 "forced" 无法到达的地方)?或者只是为了它而简单地抛出一个快速而肮脏的 new Error("enum name") 而不是我自己写一个永远不会被使用的东西是可以接受的吗?

示例中:

public static enum Color {
    RED,
    GREEN,
    BLUE;

    @Override
    public String toString() {
        switch(this) {
            case RED:
                return "Red";
            case GREEN:
                return "Green";
            case BLUE:
                return "Blue";
            default:
                /* never reached */
                throw new ThisCanNeverHappenError();
        }
    }
}

WHITE 添加到 enum 使得这个 switch 并且可能在整个代码中更多的无声源令人讨厌的错误来源,因为流控制发现它们很好。

抛出 Errors 不是一个非常明智的举动 - 大多数异常处理代码都会通过它们,它们最终会出现在奇怪的地方,可能会使您的进程无法使用。

我会推荐 IllegalStateException

Eclipse Bugzilla/Bug 374605 对此进行了长时间的讨论。

最终结果是这是一个可配置的警告,可以禁用。

将下拉列表从警告更改为忽略

如果将 "toString" 值添加为枚举实例的参数,则不需要此开关(以及对默认情况的相应处理):

public static enum Color {
    RED("Red"),
    GREEN("Green"),
    BLUE("Blue");

    private final String name;

    private Color(String name) {
      this.name = name;
    }

    @Override
    public String toString() {
      return name;
    }
}

你不应该抛出 Error。更好的例外应该是 IllegalStateException:

switch(this) {
    case RED:
        return "Red";
    case GREEN:
        return "Green";
    case BLUE:
        return "Blue";
    default:
        throw new IllegalStateException("Unexpected enum value: " + this.name());
}

换句话说,您不应该在那里使用 switch 语句。向枚举中添加一个字段。另请注意,枚举始终是 static,因此您可以删除该关键字。

public enum Color {
    RED  ("Red"),
    GREEN("Green"),
    BLUE ("Blue");

    private final String displayText;

    private Color(String displayText) {
        this.displayText = displayText;
    }
    public String getDisplayText() {
        return this.displayText;
    }
    @Override
    public String toString() {
        return this.displayText;
    }
}

您正在做出断言:/* never reached */ - 如果该断言是错误的,您可能应该抛出一个 AssertionError.

抛出 IllegalStateException 的替代建议并不合适 - 根据 javadoc:

Signals that a method has been invoked at an illegal or inappropriate time

实际情况并非如此。