Reputation: 3530
The ordinal()
method returns the ordinal of an enum instance.
How can I set the ordinal for an enum?
Upvotes: 83
Views: 113550
Reputation: 851
The accepted answer got nearly everything wrong.
It is important be aware of the risk when working with relection operations, still in many cases it is required to correct Java design features; one security case implies the need to cleanup sensitive on shutdown, which e.g. for String
-s is already awkward.
The question considered the ordinal
field only, for consistency the name
field needs to be synchronized. Following function is an extension of Enginer's answer, verified with Java 8.
public static void setEnumInPlace(final Enum<?> e, final int newOrdinal)
{
try
{
final Class<?> ecl = e.getClass();
final Field ordField = Enum.class.getDeclaredField("ordinal");
final Field nameMember = Enum.class.getDeclaredField("name");
ordField.setAccessible(true);
nameMember.setAccessible(true);
// access final ordinal
final Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(ordField, ordField.getModifiers() & ~Modifier.FINAL);
ordField.setInt(e, newOrdinal);
// sync name
final String strNewName = (String) nameMember.get(ecl.getEnumConstants()[newOrdinal]);
nameMember.set(e, strNewName);
}
catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e1)
{
System.err.println("FAILED, " + e1.getMessage());
}
}
Upvotes: 0
Reputation: 9910
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.
Upvotes: 10
Reputation: 3128
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);
}
}
Upvotes: 6
Reputation: 597382
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.
Upvotes: 72
Reputation: 2189
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
.
Upvotes: 91
Reputation: 6054
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;
}
...
}
}
Upvotes: -6
Reputation: 16153
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.
Upvotes: 0
Reputation: 24895
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...
Upvotes: 2