【问题标题】:How to deal with default case in an enum based switch?如何处理基于枚举的开关中的默认情况?
【发布时间】:2015-03-27 11:09:04
【问题描述】:

我有一个枚举,它根据枚举类型评估字符串是否有效。使用开关执行验证。默认操作是这样的: default: return false;.

一位程序员添加了一个新类型并忘记更新isValid(..),导致每次评估答案时对isValid(..) 的调用都返回false。

你认为处理它的正确方法是什么?

public enum AnswerType {
  TEXT("string"),
  INT("integer"),
  FLOAT("float");

  final String type;

  AnswerType(final String type) {
    this.type = type;
  }

  /**
   * Checks whether the given answer is valid for this answer type.
   * @param answer The provided answer.
   * @return true if the answer is valid; false otherwise.
   */
  public boolean isValid(final String answer) {

    switch (this) {
      case TEXT:
        return !StringUtils.isEmpty(answer);

      case INT:
        return NumberUtils.isDigits(answer);

      case FLOAT:
        return NumberUtils.isNumber(answer);

      default:
        return false; // Not sure this is best practise.
    }
  }
}

【问题讨论】:

  • 如果只能误打到default这种情况,抛出异常。你可以添加一个单元测试来检查没有遗漏任何值。
  • 理想情况下,摆脱 switch 语句 - 在 AnswerType 中有一个抽象方法并让每个枚举值覆盖它...
  • 合理。您更喜欢InternalErrorNotImplementedException 还是其他?

标签: java oop enums switch-statement


【解决方案1】:

这是一个奇怪的设计(并且您的代码无法达到默认情况)...为什么不将方法引入每个枚举常量中呢?

public static enum AnswerType {
  TEXT("string") {
    public boolean isValid(String answer) { return !StringUtils.isEmpty(answer); }
  },
  INT("integer") {
    public boolean isValid(String answer) { return NumberUtils.isDigits(answer); }
  },
  FLOAT("float") {
    public boolean isValid(String answer) { return NumberUtils.isNumber(answer); }
  };

  private final String type;

  AnswerType(final String type) {
    this.type = type;
  }

  /**
   * Checks whether the given answer is valid for this answer type.
   *
   * @param answer The provided answer.
   *
   * @return true if the answer is valid; false otherwise.
   */
  public abstract boolean isValid(final String answer);
}

或者,如果您使用 Java 8,则可以进一步简化代码:

public static enum AnswerType {
  TEXT("string", s -> !StringUtils.isEmpty(s)),
  INT("integer", NumberUtils::isDigits),
  FLOAT("float", NumberUtils::isNumber);

  private final String type;
  private final Predicate<String> isValid;

  AnswerType(final String type, Predicate<String> isValid) {
    this.type = type;
    this.isValid = isValid;
  }

  /**
   * Checks whether the given answer is valid for this answer type.
   *
   * @param answer The provided answer.
   *
   * @return true if the answer is valid; false otherwise.
   */
  public boolean isValid(final String answer) {
    return isValid.test(answer);
  }
}

【讨论】:

    【解决方案2】:

    如果需要随着时间的推移添加答案类型,为什么要使用枚举?您可以使用isValid 方法创建Answer 接口,然后在StringAnswerIntegerAnswer 等中实现它。然后当有人想要添加答案类型时,他们不必修改现有代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-16
      • 2010-12-22
      • 2021-09-22
      • 2018-09-16
      • 1970-01-01
      • 2015-04-17
      • 1970-01-01
      相关资源
      最近更新 更多