我可以在Java中为枚举指定序数吗?


73

ordinal()方法返回枚举实例的序数。
如何设置枚举的序数?

Answers:


67

您无法设定。它始终是常量定义的序数。请参阅Enum.ordinal()文档

返回此枚举常量的序数(其在枚举声明中的位置,其中初始常量的序数为零)。大多数程序员都不会使用此方法。它设计用于复杂的基于枚举的数据结构,例如EnumSet和EnumMap。

实际上-您不需要。如果要一些整数属性,请定义一个。


5
如果我可以指定枚举的序数,那么在将JPA与枚举一起使用时,这将更加安全……
Jack Ma

85

您可以通过更改枚举的顺序来控制序数,但是不能像中那样明确设置序数C++。一种解决方法是在枚举中为所需的数字提供一种额外的方法:

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

在这种情况下BAR.ordinal() == 0,可是BAR.getVal() == 3


9
+1确实不是一种解决方法,但确实如此。这是理想的行为。序数值被视为实现工件;如果您想分配一个整数或其他值,那就是“枚举是clases”的
含义

1
不会BAR.ordinal()返回0 afaik枚举索引从零开始
Terraego 2012年

7

正如公认的答案指出的那样,您无法设置序数。最接近此功能的是自定义属性

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;
    }

}

注意:默认情况下,如果您未指定值,则enum值的起始位置为0(not 1)。同样,1对于每个项目,值都不必增加。


4

您可以使用反射来更新序数:

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);
    }
}

1
如果愿意,可以对枚举字段重新排序。它更加容易,安全和可读。
吉利

2

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

public final int ordinal()返回此枚举常量的序数(其在枚举声明中的位置,其中初始常量的序数为零)。大多数程序员都不会使用此方法。它设计用于复杂的基于枚举的数据结构,例如EnumSet和EnumMap。

返回:此枚举常量的序数

如果你有

公共枚举日{{星期日,星期一,星期二,星期三,星期四,星期四,星期五,星期六}

那么SUNDAY的序数为0,MONDAY为1,依此类推...


3
ortinal不能保证做出上述订购!
claj 2014年

1
@claj,您可以谈谈吗?该文档似乎表明确实如此。
Celos 2014年

抱歉,@ Celos,第一个枚举确实为0,但规范中并未提及该值除单调递增外应如何分配。我想我在有效Java中读到了一些有关此警告的信息,但请不要相信。
claj 2014年

0

查看Java Enum示例文档

返回此枚举常量的序数(其在枚举声明中的位置,其中初始常量的序数为零)。大多数程序员都不会使用此方法。它设计用于复杂的基于枚举的数据结构,例如EnumSet和EnumMap。


-4

简单的答案:只需更改常数的顺序即可。第一个定义为0,第二个定义为1,依此类推。但是,如果您不断更改代码,或者枚举会包含许多值,那么这可能不切实际。您可以定义一个自定义方法来解决默认序数问题,但是请确保对此进行了详细记录以避免混淆!

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

    public int getCustomOrdinal()
    {
        if(this == ONE)
        {
            return 3;
        }
        else if(this == TWO)
        {
            return 0;
        }
        ...
    }
}

4
+1:switch语句可能比一系列if-else语句更好。
彼得·劳瑞

5
我不喜欢这种解决方案。枚举是类,因此可以包含自定义属性。我宁愿为此适当地定义一个字段以及相应的getter方法。
2014年

一般来说,这是更好的解决方案。但是这个问题问是否可以改变ordinal()的行为...
donnyton 2014年

2
为什么不申报财产“customOrdinal”,然后你会初始化枚举常量ONE(3)TWO(0)等等摆脱任何的if / else或switch语句?
Aenadon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.