亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java強制使用枚舉開關的方法的默認返回語句,涵蓋所有枚舉值

Java強制使用枚舉開關的方法的默認返回語句,涵蓋所有枚舉值

收到一只叮咚 2021-06-18 17:04:30
我有以下示例情況: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 statementMessageType getType() {    Random random = new Random();    return MessageType.values()[random.nextInt(3)];}enum MessageType {error, warning, info }我無法弄清楚getMessageForType從switch語句主體以外的其他方式從方法返回的可能性。我在想:從 I/O 數據反序列化 - 但java.lang.IllegalArgumentException: No enum constant在調用之前很久就發生了getMessageForType可能的 null 方法參數 - 但它會在switch(myType)評估時失敗java.lang.NullPointerException在這種情況下,強制使用默認的 return 語句是不舒服的,因為我不知道在這里返回什么。在這種情況下拋出異常在這里也沒有意義。這種行為背后的設計決策是什么?請幫忙,我在這里錯過了什么?
查看完整描述

3 回答

?
白豬掌柜的

TA貢獻1893條經驗 獲得超10個贊

Java強制使用枚舉開關的方法的默認返回語句覆蓋所有枚舉值......這種行為背后的設計決策是什么?


這是語言做出的一個非常重要(且正確)的決定。盡管您當前的代碼處理了枚舉的所有當前值,但這并不意味著在您的代碼編譯后很長時間內枚舉類可能會發生變化。您可能會升級第 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 條目的新枚舉,您是否希望它拋出異常?


對于例外情況,您可能需要使用:


case ...:

     return ...;

default:

     throw new IllegalStateException("unknown enum type found for" + mType);

或者也許IllegalArgumentException。


查看完整回答
反對 回復 2021-06-23
?
繁星點點滴滴

TA貢獻1803條經驗 獲得超3個贊

如果稍后編輯枚舉,添加新常量,而不重新編譯開關,會發生什么情況?這就是要防范的情況。

寫 是完全正常的default: throw new AssertionError();


查看完整回答
反對 回復 2021-06-23
?
慕碼人2483693

TA貢獻1860條經驗 獲得超9個贊

在這種情況下拋出異常在這里也沒有意義。


這是有道理的,因為即使您知道/認為您永遠不會進入這里,您也必須處理這種情況,以使您的代碼符合 Java 編譯規則,即期望該方法String在任何情況下都返回 a 。


您可以避免異常拋出,但它會使您的代碼不那么健壯:


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;

  }

}

通過這種方式,您不再需要 theswitch以及getMessageForType()方法。

該shouldReturnStringForEnum()方法可以很簡單:


@Test

public void shouldReturnStringForEnum() {

    System.out.println(getType().getMsg());

}


查看完整回答
反對 回復 2021-06-23
  • 3 回答
  • 0 關注
  • 204 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號