【问题标题】:enum.values() - is an order of returned enums deterministicenum.values() - 是返回枚举确定性的顺序
【发布时间】:2011-04-18 17:19:28
【问题描述】:

我有一个枚举SOME_ENUM

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

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

【问题讨论】:

  • 我遍历我的枚举来填充一个列表,这比我在遍历这个枚举时读取的代码中的其他地方。
  • @MitchWheat 出于同样的原因,您将依赖 List 保留顺序:因为 JDK 是一个为您提供某些保证的工具,并且依赖这些保证可以帮助您编写更简洁和更好的代码。诚然,“是否保证不改变?”的问题。不可能回答,你当然不能依赖它,没有什么可以保证。

标签: java enums specifications


【解决方案1】:

Java 语言规范使用这种显式语言:

@return 包含此枚举类型的常量的数组,按照它们被声明的顺序[Source]

所以,是的,它们将按申报顺序退回。值得注意的是,如果有人更改课程,顺序可能会随着时间而改变,因此请务必小心使用它。

【讨论】:

  • 如果有人在以后的代码版本中在中间添加了一个值,这可能会让你大吃一惊,因为它会改变其他元素的序数值(参见 Enum.ordinal())方法。出于这个原因,最好不要将序数位置作为序列化机制(即不要将其存储在数据库中)。
  • 链接到该规范的源代码?
【解决方案2】:

是的,保证按顺序退回。

但是,您应该避免依赖它以及 ordinal() 值,因为它可以在插入新项目后发生变化。

【讨论】:

  • +1 为明智的建议。关于 ordinal() 的话题,Effective Java 建议在枚举类型中添加一个成员字段。
【解决方案3】:

这取决于您的值的声明顺序。但是,不能保证您(或其他人)将来不会重新排序/插入/删除值。所以你不应该依赖订单。

Effective Java 2nd。版本将其第 31 条专用于一个密切相关的主题:使用实例字段而不是序数

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

【讨论】:

  • “不保证将来不会有人重新排序值”-但这正是我要依赖订单的原因:-)!我希望将来能够重新排序这些项目,从而改变我的程序的行为。 Bloch 关于不依赖序数是正确的,如果提问者的示例确实涉及像 EN_TWO 这样的枚举,那么他依赖于序数并且不应该这样做。但是依靠顺序是完全可以的。事实上,由于顺序是有保证的,因此专门为顺序创建一个字段将是编写冗余代码,就像《Effective Java》之类的书告诉你不要这样做。
  • @Fletch,抱歉,我不太关注你。对我来说,这听起来像是您试图将enum 用于某些目的而不是为了它的目的。
  • 假设你有著名的“Planet”枚举。在您的 UI 中,您希望按照行星与太阳的距离顺序列出行星。你怎样才能最好地做到这一点?我会在枚举类中以正确的顺序对行星常量进行排序,然后在 UI 中枚举枚举。由于订单是可靠的,这将起作用。这就是我所说的那种事情。如果有一天地球比火星更靠近太阳,当然在这样的时刻,你温暖的头脑中的第一件事就是维护你的代码!所以你去你的行星课,把地球移到火星之前。
  • @Fletch,地球已经比火星更接近太阳 ;-) 但我明白你的意思。然而,在这种情况下,行星的顺序实际上是它们与太阳的平均距离的函数,这不是一个简单的序数,因此恕我直言,最好将它存储为每个行星的不同场。然后你可以让一个简单的比较器根据它们与太阳的平均距离来比较行星,并使用这个比较器对它们进行排序。恕我直言,这是一个干净且万无一失的解决方案。而您的解决方案一旦中断,例如一位新同事决定行星应该显然按字母顺序列出;-)
  • 哈哈哈 嗯嗯嗯,反正都是阴谋,没有火星。最初我打算使用土星,但不记得它靠近哪些行星,但火星计划似乎适得其反:-)。无论如何......在这种情况下,比较器会很好,但显然有需要更多代码的缺点。我认为,如果您依赖源代码排序,那么在 cmets 类中记录这一点将是一件好事。你的同事甚至可能会读到它。
【解决方案4】:

其他的答案都不错,但不要评论这个:

"是规定还是不保证以后不改 jdk 发布了吗?”

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

也就是说,JDK 的历史显示了出色的一致性。它们不会进行大量重大更改,因此您可以确信当前的指定(不仅仅是观察到的)行为将被保留。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    • 2022-12-24
    • 1970-01-01
    相关资源
    最近更新 更多