在Java Enum定义中使用序数

时间:2013-02-08 09:42:40

标签: java enums ordinal

我注意到Java Enum Documentation表示了序数方法:

  

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

我理解在线的所有示例都建议不要使用ordinal来索引数组,而是使用EnumMap。特别是Item 33 of Effective Java 但我的问题是:在我的Enum定义中使用它是否可以? 例如,我的代码如下:

public enum Direction {
   NORTH(0, 1), NORTH_EAST(1, 1), EAST(1, 0), SOUTH_EAST(1, -1),
   SOUTH(0, -1), SOUTH_WEST(-1, 1), WEST(-1, 0), NORTH_WEST(-1, 1);

   private final int xOffset;
   private final int yOffset;

   private final static int DEGREES = 360;

   private Direction(int xOffset, int yOffset) {
     this.xOffset = xOffset;
     this.yOffset = yOffset;
   }

  public Position move(Position position) {
     return new Position(position.getX() + xOffset, position.getY() + yOffset);
  }

  public Direction rotate(int degrees) {
     int length = Direction.values().length;
     int index = (ordinal() + (degrees / (DEGREES / length))) % length;
     return Direction.values()[index];
  } 
}

正如你所看到的,我正在使用序数(),以便我可以循环指示(并返回下一个相关方向)。例如。从NORTH旋转90度将返回EAST

但是我知道使用序数不是一个好习惯,所以我想知道是否有更好的方法来做到这一点,同时仍然保持代码大小并保持可读性。

我非常感谢任何建议!

3 个答案:

答案 0 :(得分:4)

我认为这是ordinal完全可以接受的用法。事实上,在我看来,它非常简洁。

有关在ordinal代码中未使用enum的评论仅仅是为了阻止您这样做,因为大部分时间您都可以使用enum本身或EnumMap而不是。

您对EffectiveJava的引用警告您不要这样做,因为选择正确的int作为数组的偏移量是非常困难的,而且通常是不必要的。在你不适用的情况下因为a)你正确地做了这件事b)这是实现你正在寻找的功能的最简单的方法。

答案 1 :(得分:2)

如果将来有人会引入新成员,那么你的代码就会破坏,就像是WEST_FAR_AWAY(-10,0)。您需要根据申请的要求估计这是否是“轻微且可接受的缺陷”或“维护噩梦”......

答案 2 :(得分:1)

  

可以在我的Enum定义中使用它吗?

可以使用。但是不使用它并去EnumMap的原因在你提供的链接中有明确说明(引用修改,因为它引用了它的部分中描述的例子)

  

这个程序有效,甚至看起来很优雅,但外表可能是骗人的。就像编译器无法知道序数和数组索引之间的关系一样。如果你在某个地方进行了更改而忘记更新它,那么你的程序将在运行时失败。

如果你想把它包含在你的设计中,那么EnumMap似乎非常有效。