【问题标题】:How to compare with a set of enum values如何与一组枚举值进行比较
【发布时间】:2021-11-29 06:02:59
【问题描述】:

您好,我有几个月的enum

public enum Months{
JANUARY, FEBUARY, MARCH,
    APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER;
}

在服务中,我有一个方法,只有在月份大于 MARCHAPRIL, MAY, .... 时才有效。怎样才能把下面这行写得更有说服力:

public void monthCheck(Object object){
    if (object.month!= Months.JANUARY || object.month!= Months.FEBUARY || object.month != Months.MARCH){
        //do something here
    }
}

编辑:我不能使用序数,因为我还有其他用例,例如:

如果我有 PENDING、PREPARING、PREPARED、DELIEVERED、COMPLETED、RETURNED 的状态枚举。我只想显示状态为 DELIEVED、COMPLETED 或 RETURNED 的订单。 我想写一个这样的方法,只有当状态是 DELIEVED、COMPLETED 或 RETURNED 时才返回

if (order.getStatus()=={DELIEVERED, COMPLETED or RETURNED})
{return order} 
else{
throw new exception ("not valid status at this point");
}```

【问题讨论】:

  • 为什么是你自己的枚举?为什么不使用来自java.time 的那个,然后您可以使用常规的java.time 构造来查看月份是否在一个之后。
  • @M.Deinum 我还有其他用例,我将与订单状态进行比较。就像仅在状态为 PAID 或 DELIEVED 时显示,但还有其他状态,如 PREPARING_ORDER、CANCELED 等
  • 这仍然不意味着您不能使用java.time 提供的一个(或将其用于日期/月份比较)。
  • @M.Deinum 看到这种情况:我有 statuses 的枚举 public enum Statuses{ PENDING, PREPARING, PREPARED, DELIVERED, COMPLETED, RETURNED; }``` 我只想显示状态为已交付、已完成或已返回的订单。我想写这样的方法 if (order.getStatus()=={DELIIEVERED, COMPLETED or RETURNED}){return order} else{throw exception ("not valid status at this point")}
  • 您的问题是关于特定月份的而不是其他枚举。

标签: java spring spring-boot enums enumeration


【解决方案1】:

您可以使用 switch 语句。

public void monthCheck(Month month)
{
   
   switch(month)
   {
      
      //if jan, feb, or march
      case JANUARY:
      case FEBUARY:
      case MARCH:

         //do nothing
         break;

      //else
      default:

         //do stuff here.
         //be careful - month may be null, so null check if needed.

         break;
      
   }
   
}

【讨论】:

    【解决方案2】:

    你的枚举应该有 get/set 方法,比如

    public enum Months {
            JANUARY("january"), and so on;
    
            String months;
            Months(String months) {
                this.months = months;
            }
    
            public String getMonths() {
                return toggleStatus;
            }
    
    }
    

    现在,当您在项目中的任何位置执行 Months.JANUARY.getMonths() 时,这将返回“一月”值。如果你写

    JANUARY("1"), FEBRUARY("2")
    

    然后它会返回 1,2 等等

    【讨论】:

    • 我不明白为什么我们可以开箱即用地完成额外的工作
    • 因为我们不能开箱即用。 .ordinal() 方法不反映任何领域语义,而只反映代码中项目的顺序。在这种情况下使用它会为可能很难找到的讨厌的错误打开大门。如果您希望您的公司浪费数万美元来解决容易避免的问题,请随意使用它。 ;-) 那就是:注意开发人员每天的价格!
    • @suraj-gupta 为什么在概念上使用字符串来表示数字?
    • 如何在服务中使用它?我的问题的第二部分
    • @ab-al 您应该首先指定“服务”。这可能是也可能不是一个新问题。
    【解决方案3】:

    在这里试试这个代码:

    public enum Months{
    JANUARY, FEBUARY, MARCH,
        APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER;
    
    
    public void monthCheck(String str){
            if (!str.equals(Months.JANUARY) || 
                    !str.equals(Months.FEBUARY) || !str.equals(Months.MARCH)){
            //do somwthing here
            }
        }
    }
    

    在另一个类中需要时传递参数。

    【讨论】:

    • a) 我认为这甚至不能回答问题。 b)当您期望一个月时使用字符串参数是错误的,除非您正在执行反序列化之类的操作。 c) 你甚至没有解释你的答案,你只是输入了一个代码 sn-p。在 StackOverflow 上,请始终解释您的答案的概念!
    【解决方案4】:

    您应该考虑使用java.time.month(@m-deinum 已经指出了这一点)。

    如果您有充分的理由重新实现Month,并且通常对于面临类似要求的其他类型:

    您可以向枚举添加属性,因此您可以添加属性“编号”。由于枚举是不可变的,因此值必须通过构造函数设置,并且以后不能更改——这非常适合您想要实现的目标。

    public enum Month {
      JANUARY(1),
      FEBRUARY(2),
      MARCH(3),
      …
      DECEMBER(12);
    
      final public int number;
    
      Month(final int number) {
        this.number = number;
      }
    }
    

    然后您可以使用该属性轻松比较您的月份。

    final Month myMonth = …;
    if (myMonth.number > Enum.MARCH.number) {
      …
    };
    

    根据您的风格,您可以隐藏属性并提供比较方法,例如。 G。 Month.comesAfter(Month);你甚至可以让Month 实现Comparable<Month>


    小心:您可能想为此使用Enum.ordinal()。缺点是

    1. .ordinal() 不具有任何域语义,它仅反映您在代码中定义枚举常量的顺序。在这里使用它会为易于创建和难以发现的错误打开大门。
    2. 由于它不包含语义,因此在您的代码中阅读 month.ordinal() < otherMonth.ordinal() 之类的内容的开发人员可能会对此处比较的内容感到困惑,并且可能需要浏览源代码(如果它可用)从而浪费时间,更重要的是,他们失去了对要解决的实际问题的心理模型。

    提示:以单数形式命名枚举。类型的名称指的是单个实例,就像StringList 等类一样。枚举只是一个具有固定数量实例的专用类。

    【讨论】:

    • 这就是为什么在java.time 中有getValue,它返回实际数字(并在内部调用序数函数)。所以这可以很容易地规避而不添加数字。 if 实际上是错误的,因为您现在正在将整数与枚举进行比较。
    • @m-deinum 感谢您指出我示例中的错误,它已得到纠正。我还添加了您使用 java.time.Month 的建议,因为它当然是完全有效的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多