Domanda

Java states that the ordinal of the initial value is 0. Can I assume that when I create an enumeration like this :

public enum Direction {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, ...}

That the ordinal of TUESDAY is always 1, that of WEDNESDAY always 2, ...?


I'll be a bit more specific. I'm declaring an enumeration :

public enum Direction {UP,RIGHT,DOWN,LEFT}

Now there's a method to turn 90 degrees (clockwise). It's one line with ordinals :

direction = Direction.values()[direction.ordinal()+1 % Direction.values().length];

If I wouldn't use ordinals I would have to use switch statements or conditions :

switch (direction) {
    case LEFT:newdirection = Direction.UP;
    break;
  etc...
}

There are a couple advantages to using ordinals :

  • shorter code
  • faster code (negligeable)
  • if a direction is added (for example DOWN_LEFT) the implementation doesn't necessarily have to change if you put the new direction at the right spot

What do you think?

È stato utile?

Soluzione

Yes - see javadoc:

Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero).

Altri suggerimenti

Yes - but your code should not rely on it because then it will break when someone inserts Caturday.

Yes, however, relying on this makes your code brittle. If you ever change the order of the constants in the enum or add constants between them, the ordinals of some of the constants will change. So, it is for example not a good idea to store ordinal numbers in a database or a file, because if your source code changes, the data in the database or file will not be compatible anymore with your changed code.

A more robust solution is to explicitly store codes with each of your constants. For example:

public enum Status {
    NEW(0),
    PROCESSING(1),
    OK(2),
    ERROR(99);

    private final int code;

    private Status(int code) {
        this.code = code;
    }

    // Get the code for an enum constant
    public int getCode() {
        return code;
    }

    // Given a code, get the corresponding enum constant
    public static Status fromCode(int code) {
        for (Status s : Status.values()) {
            if (s.code == code) {
                return s;
            }
        }

        throw new IllegalArgumentException("Invalid code: " + code);
    }
}

You can also enforce indexes like this:

enum Direction {
  MONDAY(1),
  TUESDAY(2);
  // etc...

  private int value;    

  private Direction(int value) {
    this.value = value;
  }

  public int getValue() {
    return value;
  }
}

Yes. However, relying on that is not the best idea if you ever want to reorder or add new enums in different places, or if you find a reason to change an existing value. I find it better to give them an actual value/meaning aside from their ordinal value and name.

The problem with ordinals is that they depend on the order of declaration of the enum values. If at some point a new value is added to the enumeration, and it's added in the middle of the others, then the ordinals will change, invalidating all code that depended on a specific ordinal value.

If you absolutely must assign a fixed number to an ordinal value, this might be of use:

enum Directions {
    NORTH(1),
    SOUTH(2),
    WEST(3),
    EAST(4);
    private int code;
    Directions(int code) {
        this.code = code;
    }
    public int getCode() {
        return code;
    }
}

In the above snippet, a code attribute is associated to each enumeration value, and you can be sure that it will always have the same value - the one passed in the constructor.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top