【问题标题】:What is a good "unreachable" Error for switches?对于交换机来说,什么是好的“无法访问”错误?
【发布时间】:2016-03-15 15:44:54
【问题描述】:

Eclipse 迫使我对任何 switch 使用 default 案例,包括列出所有声明的 enum 值的案例,据称是因为语言规范 [1]。这是不幸的,因为并行开发该项目的 Android Studio 不会,并且自然会警告我所有 switches,如果 enum 更改,它们将变得不完整。虽然我更喜欢后一种行为,因为前者使enum 的更改实际上更多容易出错(参见下面的示例),但我无法选择,所以我需要找到如何做到这一点适合两者。我想如果代码中有一个地方在任何情况下都无法访问,但仍然不能删除该行,那么在那里抛出Error 似乎是很自然的事情。但是哪一个,对于这种情况有一个普遍接受的子类(可能扩展到其他“强制”无法到达的地方)?或者只是为了它而简单地抛出一个快速而肮脏的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 以及可能在整个代码中更多地成为令人讨厌的错误源,因为流控制发现它们很好。

【问题讨论】:

  • 如果你定义了你自己的,你可以使用任何你想要的东西,但是你可能想要继承RuntimeException,因为你不希望有throws 规范来定义不应该发生的异常。跨度>
  • 这是not如何使用条件的完美示例。改为使用多态性并将字符串作为枚举实例的属性。
  • @skyking:我读到Error没有被勾选,以免鼓励人们抓住它。
  • @TheVee 你可以定义像RED("Red") 这样的实例并添加一个构造函数private Color(String name) 将参数分配给一个字段 - 然后在toString() 中返回该字段。
  • Error 没有被选中因为它意味着完全不同的东西。似乎你只熟悉 C 风格的枚举;阅读有关 Java 枚举的官方教程。用易于理解的例子清楚地解释了这一点。

标签: java exception jls


【解决方案1】:

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

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

将下拉菜单从警告更改为忽略

【讨论】:

    【解决方案2】:

    你不应该抛出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;
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果您将“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;
          }
      }
      

      【讨论】:

        【解决方案4】:

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

        我会推荐IllegalStateException

        【讨论】:

        • “明智的电影” 你是说move吗?
        • 传递它们或多或少是有意的——这是一个非常严重的错误,我不希望程序尝试任何恢复并无条件地给我堆栈跟踪。此外,观察它是尝试检查每一次发生的原因的充分理由,以防止在生产中发生这种情况。
        • @TheVee 如果没有发生,你不在乎它是异常还是错误,如果确实发生了,你最好在那里有异常。
        【解决方案5】:

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

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

        表示方法在非法或不适当的时间被调用

        实际情况并非如此。

        【讨论】:

          猜你喜欢
          • 2011-04-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-23
          • 2012-08-22
          • 1970-01-01
          • 1970-01-01
          • 2012-02-03
          相关资源
          最近更新 更多