Java强制从带有枚举开关的方法返回默认的返回语句,并覆盖所有枚举

时间:2018-08-01 20:09:14

标签: java enums switch-statement return

我有以下示例情况:

<ol class="ranking">
  <li><a href="https://www.havocscope.com/tag/united-states/">United States</a><span>$625.63 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/china/">China</a><span>$261 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/mexico/">Mexico</a><span>$126.08 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/spain/">Spain</a><span>$124.06</span></li>
  <li><a href="https://www.havocscope.com/italy-economy/">Italy</a><span>$111.05 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/japan/">Japan</a><span>$108.3 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/canada/">Canada</a><span>$77.83</span></li>
  <li><a href="https://www.havocscope.com/tag/india/">India</a><span>$68.59 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/united-kingdom/">United Kingdom</a><span>$61.96</span></li>
  <li><a href="https://www.havocscope.com/tag/russia/">Russia</a><span>$49.04 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/germany/">Germany</a><span>$39.67 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/south-korea/">South Korea</a><span>$26.2 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/indonesia/">Indonesia</a><span>$23.05 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/philippines/">Philippines</a><span>$17.27 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/turkey/">Turkey</a><span>$17.16 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/brazil/">Brazil</a><span>$17 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/australia/">Australia</a><span>$14.62 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/colombia/">Colombia</a><span>$14.50 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/venezuela/">Venezuela</a><span>$14.19 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/thailand/">Thailand</a><span>$13.95 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/paraguay/">Paraguay</a><span>$13 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/morocco/">Morocco</a><span>$12.7 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/iran/">Iran</a><span>$10.64 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/guatemala/">Guatemala</a><span>$10.11 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/saudi-arabia/">Saudi Arabia</a><span>$10.1 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/france/">France</a><span>$9.85 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/nigeria/">Nigeria</a><span>$8.4 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/afghanistan/">Afghanistan</a><span>$7.3 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/israel/">Israel</a><span>$7.05 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/peru/">Peru</a><span>$6.7 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/pakistan/">Pakistan</a><span>$6.53 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/iraq/">Iraq</a><span>$5.17 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/bulgaria/">Bulgaria</a><span>$4.74 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/hungary/">Hungary</a><span>$4.6 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/switzerland/">Switzerland</a><span>$4.5 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/ukraine/">Ukraine</a><span>$4.31 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/south-africa/">South Africa</a><span>$3.93 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/greece/">Greece</a><span>$3.85 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/egypt/">Egypt</a><span>$3.79 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/malaysia/">Malaysia</a><span>$2.99 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/ireland/">Ireland</a><span>$2.98 Billion</span></li>
  <li><a href="https://www.havocscope.com/tag/taiwan/">Taiwan</a><span>$2.60 Billion</span></li>
</ol>

除了public void shouldReturnStringForEnum() { MessageType myType = getType(); System.out.println(getMessageForType(myType)); } String getMessageForType(MessageType myType) { switch(myType) { case error: return "Error type"; case warning: return "Warning type"; case info: return "Info type"; } } // <= error: missing return statement MessageType getType() { Random random = new Random(); return MessageType.values()[random.nextInt(3)]; } enum MessageType {error, warning, info } 语句的主体之外,我无法确定以其他方式从方法getMessageForType返回的可能性。 我在想:

  • 从I / O数据反序列化-但是随后switch发生在调用java.lang.IllegalArgumentException: No enum constant之前很久
  • 可能为null的方法参数-但在使用getMessageForType进行switch(myType)评估时,它将失败

在这种情况下强制使用默认的return语句是不舒服的,因为我不知道在这里返回什么。在这种情况下抛出异常在这里也没有意义。这种行为背后的设计决策是什么?

请帮助,我在这里想念什么?

4 个答案:

答案 0 :(得分:3)

如果稍后编辑枚举,添加新常量而不重新编译开关会发生什么情况?情况就是这样。

default: throw new AssertionError();是很正常的。

答案 1 :(得分:2)

  

在这种情况下引发异常在这里也没有意义。

这是有道理的,因为即使您知道/认为您永远不会在这里输入,也必须处理这种情况才能使代码符合Java编译规则,该规则要求该方法在任何情况下都返回String案件。

您可以避免引发异常,但这会使代码的健壮性降低:

String getMessageForType(MessageType myType) {
   switch(myType) {
     case error:
        return "Error type";
     case warning:
        return "Warning type";       
   }
   return "Info type";
 }

假设添加了一个fine枚举值,而您没有更新getMessageForType(),则将返回“信息类型”。

所以这是一个很好的方法:

String getMessageForType(MessageType myType) {
   switch(myType) {
      case error:
        return "Error type";
    case warning:
        return "Warning type";
    case info:
        return "Info type";
   }
   throw new RuntimeException("Should not happen here ! We get the enum value " + myType);
 }

更好的方法是将与每个枚举关联的String添加为枚举的实例字段:

enum MessageType {

 ERROR("Error type"), WARNING("Warning type"), INFO("Info type");

  private String msg;

  MessageType(String msg){ 
    this.msg = msg;
  }

  public String getMsg(){
     return msg;
  }
}

通过这种方式,您不再需要switchgetMessageForType()方法。
shouldReturnStringForEnum()方法可能很简单:

@Test
public void shouldReturnStringForEnum() {
    System.out.println(getType().getMsg());
}

答案 2 :(得分:0)

通过使用return的情况,您可以switch语句中的default默认值,如下所示:

String getMessageForType(MessageType myType) {
    switch(myType) {
        case error:
            return "Error type";
        case warning:
            return "Warning type";
        case info:
            return "Info type";
        default:
            return "unknown message type";
    }
} // <= no error anymore

您也可以在String语句之前的switch中定义一个默认值,并在switch中不匹配的情况下返回默认值:

String getMessageForType(MessageType myType) {
    String r = "unknown message type";
    switch(myType) {
        case error:
            r = "Error type";
        case warning:
            r = "Warning type";
        case info:
            r = "Info type";
    }
    return r;
} // <= no error anymore

答案 3 :(得分:0)

  

Java强制从带有枚举开关的方法中使用默认的return语句覆盖所有枚举值...这种行为背后的设计决策是什么?

这是该语言做出的非常重要(也是正确的)决定。即使您当前的代码处理了枚举的所有当前值,但这并不意味着枚举类可能会在编译代码后很长一段时间内发生变化。您可能会升级第3方库,并且可能添加另一个枚举值,导致您的代码在没有默认值的情况下在运行时无效。

即使您控制枚举代码,这也不意味着其他开发人员(或将来的您)可能会向枚举添加另一个值,并且无法更新switch语句。编写以这种方式向前兼容的代码通常是一种最佳实践,在这种情况下,对于强制该行为的行为至关重要。

  

我不知道该怎么返回。

然后问题归结为是否引发异常。程序员每天都在努力处理无效的枚举值或其他异常情况。在这种情况下,您需要问自己想要发生什么?这是不应该引起的烦恼还是更严重的错误?呼叫者应该处理异常还是RuntimeException可以吗?这些是您需要在应用程序上下文中回答的问题。

最后,我不了解您,但是我认识的大多数程序员都剪切并粘贴了大量代码。尽管此枚举可能永远不会扩展,但将来的枚举 会得到扩展,并且可以通过适当处理此案而做出明智的决定。

  

在这种情况下强制使用默认的return语句是不舒服的...

"Unknown type"可能是一个不错的选择。

case ...:
     return ...;
default:
     // here in case someone updates the enum and forgets to update this code
     return "Unknown type";
  

在这种情况下引发异常在这里也没有意义。

这有点取决于返回默认"unknown"字符串的金额。如果有一个新的枚举缺少个案条目,您是否要它引发异常?

对于例外情况,您可能需要使用:

case ...:
     return ...;
default:
     throw new IllegalStateException("unknown enum type found for" + mType);

IllegalArgumentException