1

Hello I have an enum of months.

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

In the service I have a method that should only work if the month is greater than MARCH i.e. APRIL, MAY, ..... How can I write the following line more eloquently:

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

Edit: I can not use ordinal because I have other use cases like:

If I have enum of stasuses PENDING, PREPARING, PREPARED, DELIEVERED, COMPLETED, RETURNED. And I only want to show orders with statuses DELIEVERED, COMPLETED or RETURNED. I want to write a method like that only return if the status is either of DELIEVERED, COMPLETED or RETURNED

if (order.getStatus()=={DELIEVERED, COMPLETED or RETURNED})
{return order} 
else{
throw new exception ("not valid status at this point");
}```
ab AL
  • 31
  • 1
  • 9
  • 2
    Why your own enum? WHy not use the one from `java.time`, you could then use the regular `java.time` constructs to see if the month is after one. – M. Deinum Nov 29 '21 at 07:12
  • @M.Deinum I have other use cases too where I will be comparing with statuses of the order. Like showing only if it the status is PAID or DELIEVERED, but there are other statuses like PREPARING_ORDER, CANCELLED etc – ab AL Nov 29 '21 at 07:37
  • Which still doesn't mean you cannot use the `java.time` provided one (or use that for date/month comparisons). – M. Deinum Nov 29 '21 at 07:51
  • @M.Deinum see this scenario: I have enum of stasuses public enum Statuses{ PENDING, PREPARING, PREPARED, DELIEVERED, COMPLETED, RETURNED; }``` I only want to show orders with statuses DELIEVERED, COMPLETED or RETURNED. I want to write a method like this if (order.getStatus()=={DELIEVERED, COMPLETED or RETURNED}){return order} else{throw exception ("not valid status at this point")} – ab AL Nov 29 '21 at 08:13
  • Your questions is about months specific not other enums. – M. Deinum Nov 29 '21 at 08:15
  • @M.Deinum yes but I will like to have a uniform approach over the whole application – ab AL Nov 29 '21 at 09:23
  • Then ask that question and not only for months as that makes it a whole different question imho. – M. Deinum Nov 29 '21 at 09:34
  • @m-deinum Let's keep it friendly! There may even be reasons to introduce your own `Month` class. – Amadán Nov 29 '21 at 09:59

3 Answers3

0

Your enum should have get/set methods like

public enum Months {
        JANUARY("january"), and so on;

        String months;
        Months(String months) {
            this.months = months;
        }

        public String getMonths() {
            return toggleStatus;
        }

}

Now when you do Months.JANUARY.getMonths() anywhere in your project this will return "january" value. If you write

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

Then it will return 1,2 and so on

Suraj Gupta
  • 390
  • 1
  • 9
  • 25
  • I do not understand why the additional work when we can do it out-of-the-box – chaitanya guruprasad Nov 29 '21 at 06:15
  • Because we can _not_ do it out-of-the-box. The `.ordinal()` method does not reflect any domain semantics but only the order of items in the code. Using it in this case would open the gates for nasty bugs that may be very hard to find. Feel free to use it, if you want your company to waste tens of thousands of dollars for fixing easily avoidable problems. ;-) That is: mind a developer's price per day! – Amadán Nov 29 '21 at 06:49
  • @suraj-gupta Why use a string for what is a number conceptionally? – Amadán Nov 29 '21 at 07:12
  • How can I use this in the service? The second part of my question – ab AL Nov 29 '21 at 07:33
  • @ab-al You should specify "the service" first. It might or might not be a new question. – Amadán Nov 29 '21 at 07:49
  • @Amadán I edited the question now – ab AL Nov 29 '21 at 08:20
  • @amandan That's just an example to how you can use enums to your benefit, you can use anything as a string and then convert to your required format and compare. In this case use 1,2 and Integer.parseInt, compare the numbers and you are done! If we can broaden the thinking we can leverage the way we want enums/or rather any other concepts. Good luck!! – Suraj Gupta Nov 29 '21 at 12:48
0

You can use a switch statement.

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;
      
   }
   
}
davidalayachew
  • 1,279
  • 1
  • 11
  • 22
-2

You should consider using java.time.month (@m-deinum already pointed that out).

In case you have got valid reasons for reimplementing Month and as a rule for other types facing similar requirements:

You can add properties to your enum, so you can add a property "number". As enums are immutable, the value must be set through constructor and cannot ever be changed later—which is perfect for what you want to achieve.

public enum Month {
  JANUARY(1),
  FEBRUARY(2),
  MARCH(3),
  …
  DECEMBER(12);

  final public int number;

  Month(final int number) {
    this.number = number;
  }
}

You can then easily compare your months using that property.

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

Depending on your style you can hide the property and provide methods for comparing, e. g. Month.comesAfter(Month); you may even make Month implement Comparable<Month>.


CAREFUL: You might be tempted to use Enum.ordinal() for that. The downsides are

  1. .ordinal() does not bear any domain semantics, it merely reflects the order in wich you defined the enum constants in your code. Using it here would open the gates for easy-to-create and hard-to-find bugs.
  2. As it does not bear semantics a developer reading something like month.ordinal() < otherMonth.ordinal() in your code might be confused about what's being compared here and might need to browse the source code (if it available) thus wasting time and—more important—losing their mental model on the actual problem to solve.

tip: Name the enum in singular. The type's name refers to a single instance as it is the case with classes like String, List and so on. An enum is just a specialized class with a fixed number of instances.

Amadán
  • 718
  • 5
  • 18
  • 1
    Which is why in the `java.time` one there is `getValue` which returns the actual number (and internally calls the ordinal function). So this can be circumvented quite easily without adding numbers. The `if` is actually wrong as you are now comparing an Integer to an enum. – M. Deinum Nov 29 '21 at 09:33
  • @m-deinum Thanks for pointing me to the bug in my example, it has been corrected. Also I added your suggestion to use `java.time.Month` as it—of course—is perfectly valid. – Amadán Nov 29 '21 at 10:09