5

我注意到Java 枚举文档说明了序数方法:

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

我了解所有在线示例,这些示例建议不要使用ordinal索引来索引数组,而是使用索引EnumMap。特别是 Effective Java 的第 33 条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];
  } 
}

如您所见,我正在使用 ordinal() 以便我可以循环浏览方向(并返回下一个相关方向)。例如,旋转 90 度NORTH将返回EAST

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

我会非常感谢任何建议!

4

3 回答 3

4

我会说这是完全可以接受的使用ordinal. 事实上,在我看来,它非常简洁。

关于不在代码中使用的注释ordinal只是enum为了阻止你这样做,因为大多数时候你可以使用它enum本身或EnumMap代替。

您的参考EffectiveJava是警告您不要这样做,因为选择正确int的用作数组的偏移量是令人担忧的并且通常是不必要的。在您的情况下不适用,因为a)您做得正确并且b)这是实现您正在寻找的功能的最简单方法。

于 2013-02-08T09:51:42.990 回答
2

如果将来有人引入新成员是枚举,您的代码将会中断,例如 WEST_FAR_AWAY(-10, 0)。您需要根据您的应用程序的要求来估计这是一个“轻微且可接受的缺陷”还是“维护噩梦”......

于 2013-02-08T10:28:29.473 回答
1

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

可以使用。但是您提供的链接中很好地说明了不使用它并使用 EnumMap 的原因(引用已修改,因为它指的是它的部分中描述的示例)

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

如果您将 EnumMap 包含在您的设计中以获取方向,那么 EnumMap 似乎非常有效。

于 2013-02-08T09:55:35.353 回答