Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing an enum value before it's defined

Tags:

java

enums

If I had the enum

public enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

what would be the best way to save the value TUESDAY in the value MONDAY (for example for use in a method Days#nextDay). I would have thought MONDAY(TUESDAY) would have worked, but I cant do this as TUESDAY is not yet defined. Is there a workaround for this (for example MONDAY(Days.valueOf("TUESDAY"))) or do I need to write a separate method?

Thank you in advance

like image 696
Fraser Price Avatar asked Feb 03 '15 11:02

Fraser Price


People also ask

Can we get an enum by value?

Get the value of an Enum To get the value of enum we can simply typecast it to its type. In the first example, the default type is int so we have to typecast it to int. Also, we can get the string value of that enum by using the ToString() method as below.

Are enums a code smell?

Many people consider Enums as a code smell and an anti-pattern in OOPs. Certain books have also cited enums as a code smell, such as the following. In most cases, enums smell because it's frequently abused, but that doesn't mean that you have to avoid them. Enums can be a powerful tool in your arsenal if used properly.


2 Answers

Easiest and preferred way would be using one of standard classes like DayOfWeek introduced in Java 8. You could simply use its plus(days) method to move to next days like

DayOfWeek foo = DayOfWeek.MONDAY.plus(1);//TUESDAY
DayOfWeek bar = DayOfWeek.SUNDAY.plus(1);//MONDAY 

but if your real problem is about some other enums you can solve it in few ways.


One of ways could be letting each Enum instance store its next instance. We could set up their value in static block, after all enum values will be already declared:

enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

    static{
        MONDAY.next = TUESDAY;
        TUESDAY.next = WEDNESDAY;
        WEDNESDAY.next = THURSDAY;
        THURSDAY.next = FRIDAY;
        FRIDAY.next = SATURDAY;
        SATURDAY.next = SUNDAY;
        SUNDAY.next = MONDAY;
    }

    private Days next;

    public Days nextDay() {
        return next;
    }

}

MONDAY.nextDay() will return TUESDAY.


Other way could be simply adding method which will use position of current enum to get next element:

enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

    private static final Days[] VALUES = Days.values(); // store result of values()
                                                        // to avoid creating new array
                                                        // each time we use values()
    public Days nextDay() {
        return VALUES[(ordinal() + 1) % 7];
    }

}
  • values() returns array of all values from current enum in order of their declaration
  • ordinal() returns position of current enum indexed from 0 (0-MONDAY, 1-TUESDAY, and so on).
like image 160
Pshemo Avatar answered Oct 29 '22 19:10

Pshemo


I would suggest to create an abstract method, which is implemented in all the constants. The return value will be the next day:

public enum Days {
    MONDAY() {
        public Days nextDay() {
            return TUESDAY;
        }
    };
    //TODO: Implement the other days accordingly.

    abstract Days nextDay();
}
like image 40
Konstantin Yovkov Avatar answered Oct 29 '22 19:10

Konstantin Yovkov