【问题标题】:Can I specify ordinal for enum in Java?我可以在 Java 中为枚举指定序数吗?
【发布时间】:2011-07-19 08:59:28
【问题描述】:

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

【问题讨论】:

    标签: java enums


    【解决方案1】:

    正如接受的答案指出的那样,您不能设置序数。最接近这一点的是自定义属性

    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(不是 1)开始。此外,每个项目的值不必增加1

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 如果你愿意这样做,你不妨重新排序枚举字段。它更简单、更安全、更易读。
      【解决方案3】:

      你不能设置它。它始终是常量定义的序数。见documentation for Enum.ordinal()

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

      实际上 - 你不应该这样做。如果你想要一些整数属性,定义一个。

      【讨论】:

      • 如果我可以指定枚举的序数,当使用JPA和枚举时,会更安全...
      【解决方案4】:

      您可以通过更改枚举的顺序来控制序数,但不能像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

      【讨论】:

      • +1 除了这不是一种解决方法,真的。这是期望的行为。序数值被认为是一个实现工件;如果你想分配一个整数或其他值,那就是“枚举是类”太棒了......
      • 不会 BAR.ordinal() 返回 0 afaik 枚举索引是从零开始的
      【解决方案5】:

      简单的答案:只需更改常量的顺序即可。第一个定义为 0,第二个定义为 1,依此类推。但是,如果您不断更改代码,或者枚举将有很多值,这可能不切实际。您可以定义一个自定义方法来解决默认序数,但请确保它有据可查以避免混淆!

      public enum Values
      {
          ONE, TWO, THREE, FOUR;
      
          public int getCustomOrdinal()
          {
              if(this == ONE)
              {
                  return 3;
              }
              else if(this == TWO)
              {
                  return 0;
              }
              ...
          }
      }
      

      【讨论】:

      • +1:一个 switch 语句可能比一系列 if-else 语句更好。
      • 我不喜欢这个解决方案。枚举是类,因此可以包含自定义属性。我宁愿为此正确定义一个字段和相应的 getter 方法。
      • 一般来说这是更好的解决方案。但问题是问是否有可能改变 ordinal() 的行为...
      • 为什么不只声明一个属性“customOrdinal”,然后将枚举常量初始化为 ONE(3)TWO(0) 等以摆脱任何 if/else 或 switch 语句?跨度>
      【解决方案6】:

      查看 Java Enum examplesdocs

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

      【讨论】:

        【解决方案7】:

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

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

        返回: 这个枚举常量的序数

        如果你有

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

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

        【讨论】:

        • ortinal 不保证给上面的顺序!
        • @claj,你能扩展一下吗?文档似乎表明确实如此。
        • 对不起@Celos,第一个枚举确实是0,但是除了单调递增之外,规范没有提到应该如何分配值。我想我在 Effective Java 中读过一些关于这个警告的东西,但不要相信我的话。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-28
        • 2012-07-12
        • 1970-01-01
        • 1970-01-01
        • 2017-03-31
        • 2010-10-06
        相关资源
        最近更新 更多