80

The ordinal() method returns the ordinal of an enum instance.
How can I set the ordinal for an enum?

Pang
  • 9,564
  • 146
  • 81
  • 122
Keating
  • 3,380
  • 10
  • 34
  • 42

7 Answers7

89

You can control the ordinal by changing the order of the enum, but you cannot set it explicitly like in C++. One workaround is to provide an extra method in your enum for the number you want:

enum Foo {
  BAR(3),
  BAZ(5);
  private final int val;
  private Foo(int v) { val = v; }
  public int getVal() { return val; }
}

In this situation BAR.ordinal() == 0, but BAR.getVal() == 3.

Matt
  • 2,139
  • 1
  • 16
  • 20
  • 11
    +1 except this isn't a workaround, really. it's desired behavior. the ordinal value is considered an implementation artifact; if you want to assign an integer or other value, that's what "enums are clases" is so great... – andersoj Mar 21 '11 at 01:43
  • 1
    wouldnt BAR.ordinal() return 0 afaik enum indexes are zero based – Maarten Blokker Mar 10 '12 at 14:59
72

You can't set it. It is always the ordinal of the constant definition. See the documentation for Enum.ordinal():

Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap.

And actually - you should not need to. If you want some integer property, define one.

Jacob Marble
  • 28,555
  • 22
  • 67
  • 78
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
10

As the accepted answer points out, you can't set the ordinal. The closest you can get to this is with a custom property:

public enum MonthEnum {

    JANUARY(1),
    FEBRUARY(2),
    MARCH(3),
    APRIL(4),
    MAY(5),
    JUNE(6),
    JULY(7),
    AUGUST(8),
    SEPTEMBER(9),
    OCTOBER(10),
    NOVEMBER(11),
    DECEMBER(12);

    MonthEnum(int monthOfYear) {
        this.monthOfYear = monthOfYear;
    }

    private int monthOfYear;

    public int asMonthOfYear() {
        return monthOfYear;
    }

}

Note: By default, enum values start at 0 (not 1) if you don't specify values. Also, the values do not have to increment by 1 for each item.

Agi Hammerthief
  • 2,114
  • 1
  • 22
  • 38
blubb
  • 9,510
  • 3
  • 40
  • 82
5

You can update ordinal using reflection:

private void setEnumOrdinal(Enum object, int ordinal) {
    Field field;
    try {
        field = object.getClass().getSuperclass().getDeclaredField("ordinal");
        field.setAccessible(true);
        field.set(object, ordinal);
    } catch (Exception ex) {
        throw new RuntimeException("Can't update enum ordinal: " + ex);
    }
}
Enginer
  • 3,048
  • 1
  • 26
  • 22
  • 2
    If you're willing to do this, you might as well reorder the enum fields. It's easier, safer and more readable. – Gili Feb 01 '19 at 21:32
2

From http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Enum.html

public final int ordinal()Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap.

Returns: the ordinal of this enumeration constant

If you have

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

then SUNDAY has an ordinal of 0, MONDAY is 1, and so on...

SJuan76
  • 24,532
  • 6
  • 47
  • 87
  • 3
    ortinal is not guaranteed to give the ordering above! – claj Jan 10 '14 at 14:02
  • 1
    @claj, can you expand on that a bit? The documentation seems to indicate it does. – Celos Aug 26 '14 at 13:01
  • Sorry @Celos, the first enum is indeed 0, but the spec does not mention how the value should be assigned at all apart from being monotonically increasing. I think I read something about this caveat in Effective Java or so, but don't take my word for it. – claj Aug 26 '14 at 13:55
0

Check out the Java Enum examples and docs

Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap.

Piyush Mattoo
  • 15,454
  • 6
  • 47
  • 56
-6

The easy answer: just change the order of the constants. The first defined will be 0, the second will be 1, etc. However, this may not be practical if you have constantly changing code, or enums will many many values. You can define a custom method to work around the default ordinal, but MAKE SURE it is well documented to avoid confusion!

public enum Values
{
    ONE, TWO, THREE, FOUR;

    public int getCustomOrdinal()
    {
        if(this == ONE)
        {
            return 3;
        }
        else if(this == TWO)
        {
            return 0;
        }
        ...
    }
}
donnyton
  • 5,874
  • 9
  • 42
  • 60
  • 4
    +1: A switch statement might be better than a series of if-else statements. – Peter Lawrey Mar 21 '11 at 07:44
  • 6
    I dislike this solution. Enums are classes and therefore can contain custom properties. I'd rather properly define a field for this and a corresponding getter method. – Atmocreations May 21 '14 at 09:04
  • That is the better solution in general. But the question asked if it's possible to change the behavior of ordinal()... – donnyton Sep 05 '14 at 20:46
  • 2
    why not just declare a property "customOrdinal" and then you'd initialize your enum constants as `ONE(3)` , `TWO(0)` etc. to get rid of any if/else or switch statements? – techfly May 24 '17 at 08:58