如何保证编译时枚举切换的完整性?

2022-08-31 20:18:00

我有几个开关语句来测试.所有值都必须由语句在语句中由语句处理。在代码重构期间,可能会发生收缩和增长的情况。当 收缩时,编译器会引发错误。但是,如果 增长,则不会引发任何错误。匹配状态被遗忘并产生运行时错误。我想将此错误从运行时移动到编译时。从理论上讲,应该可以在编译时检测到丢失的案例。有没有办法做到这一点?enumenumswitchcaseenumenumenumenum

问题已经存在“如何检测添加到枚举中并且未在交换机中处理的新值”,但它不包含仅与Eclipse相关的解决方法的答案。


答案 1

Effective Java 中,Joshua Bloch 建议创建一个抽象方法,该方法将为每个常量实现。例如:

enum Color {
    RED   { public String getName() {return "Red";} },
    GREEN { public String getName() {return "Green";} },
    BLUE  { public String getName() {return "Blue";} };
    public abstract String getName();
}

这将作为更安全的开关,强制您在添加新常量时实现该方法。

编辑:为了澄清一些混淆,这是使用常规的等效项:switch

enum Color {
    RED, GREEN, BLUE;
    public String getName() {
        switch(this) {
            case RED:   return "Red";
            case GREEN: return "Green";
            case BLUE:  return "Blue";
            default: return null;
        }
    }
}

答案 2

另一种解决方案使用功能方法。您只需要根据下一个模板声明枚举类:

public enum Direction {

    UNKNOWN,
    FORWARD,
    BACKWARD;

    public interface SwitchResult {
        public void UNKNOWN();
        public void FORWARD();
        public void BACKWARD();
    }

    public void switchValue(SwitchResult result) {
        switch (this) {
            case UNKNOWN:
                result.UNKNOWN();
                break;
            case FORWARD:
                result.FORWARD();
                break;
            case BACKWARD:
                result.BACKWARD();
                break;
        }
    }
}

如果您尝试在没有至少一个枚举常量的情况下使用它,则会收到编译错误:

getDirection().switchValue(new Direction.SwitchResult() {
    public void UNKNOWN() { /* */ }
    public void FORWARD() { /* */ }
    // public void BACKWARD() { /* */ } // <- Compilation error if missing
});