enum.values()-是确定性返回的枚举的顺序


105

我有一个枚举SOME_ENUM

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

SOME_ENUM.values()始终返回枚举枚举声明的顺序: EN_ONE, EN_TWO, EN_THREE?是规则还是不能保证在下一个JDK版本中不会更改它?


1
我遍历我的枚举以填充一个列表,而不是在我遍历该枚举的代码中的其他位置。
Skarab 2010年

11
@MitchWheat出于同样的原因,您将依赖于List的保留顺序:因为JDK是一种为您提供一定保证的工具,而依靠这些保证可以帮助您编写更简洁,更好的代码。诚然,问题“是否保证不会更改?” 无法回答,您当然不能依靠,没有任何保证。
Fletch 2012年

Answers:


144

Java语言规范使用以下显式语言:

@按声明顺序返回包含此枚举类型的常量的数组[源]

因此,是的,它们将按声明顺序返回。值得注意的是,如果有人更改课程,顺序可能会随着时间而改变,因此请务必谨慎使用。


1
如果有人在以后的代码版本中在中间添加一个值,这可能会使您不知所措,因为这会更改其他元素的顺序值(请参见Enum.ordinal())方法。因此,最好不要将序数位置作为序列化机制(即,不要将其存储在数据库中)。
马特

1
链接到该规范的来源?
Dan Grahn


16

是的,保证按此顺序返回它们。

但是,您应该避免依赖于该ordinal()值,因为例如在插入新项目后它可能会更改。


+1为贤哲建议。关于ordinal()主题,Effective Java建议将成员字段添加到枚举类型。
ide

9

它由声明值的顺序决定。但是,不能保证您(或其他人)将来不会重新排序/插入/删除值。因此,您不应该依赖订单。

有效的Java 2nd。Edition将其第31项专用于一个紧密相关的主题:使用实例字段代替普通的字段

永远不要从其序数中得出与枚举相关的值;而是将其存储在实例字段中。


3
“不保证某人将来不会对值进行重新排序”-但这正是我要依赖该命令的原因:-)!我希望以后能够重新订购商品,从而改变程序的行为。Bloch对不依赖序数是正确的,如果问问者的示例确实涉及EN_TWO之类的枚举,那么他就依赖序数,因此不应该这样做。但是依靠顺序是完全可以的。实际上,为了保证顺序,专门为订单创建一个字段将编写冗余代码,像有效Java这样的事情书告诉您不要这样做。
Fletch 2012年

@Fletch,对不起,我不太了解您。对我来说,这听起来像是您正试图将其enum用于非预期目的。
彼得Török

假设您有著名的“行星”枚举。在您的用户界面中,您要按行星到太阳的距离顺序列出它们。您如何最好地做到这一点?我将以正确的顺序在enum类中对行星常量进行排序,然后仅在UI中枚举枚举。由于顺序是可靠的,因此可以使用。这就是我在说的那种话。如果有一天地球比火星更靠近太阳,那么当然,在这样的时刻,您最热衷的第一件事就是维护您的代码!因此,您要上行星课,然后将地球移到火星之前。
Fletch 2012年

@Fletch,地球已经比火星更靠近太阳了;-)但是我明白你的意思了。但是,在这种情况下,行星的顺序实际上是它们与太阳的平均距离的函数,这不是一个简单的序数,因此恕我直言,最好将其存储为每个行星的不同场。然后,您可以让一个琐碎的比较器根据它们与太阳的平均距离比较行星,并使用此比较器对其进行排序。恕我直言,这是一种干净,简单的解决方案。而解决方案的假期,因为一旦如新同事决定行星应该明显地按字母顺序列出;-)
彼得Török

1
哈哈哈嗯,好吧,反正都是阴谋,没有火星。最初,我打算使用土星,但不记得它在哪颗行星附近,但火星计划似乎事与愿违:-)。无论如何...在这种情况下,比较器会很好,但是显然需要更多代码。我认为,如果您依赖于源代码排序,那么在类注释中进行记录将是一件好事。您的同事甚至可以阅读。
2012年

7

其他答案很好,但是不要对此发表评论:

“这是规则还是不能保证在下一个Jdk版本中不会更改?”

我不相信将来的JDK会存在保证,因此您甚至不必担心它们。没有办法强制执行,将来的JDK领导可能会决定放弃这种保证。就像威斯敏斯特议会制一样:“没有议会可以约束未来的议会。”

就是说,JDK的历史揭示了极好的一致性。它们并没有进行很多重大更改,因此您可以确信将保留当前指定的(不仅仅是观察到的)行为。

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.