Java 使用枚举序数是一种好习惯吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44654291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:39:42  来源:igfitidea点击:

Is it good practice to use ordinal of enum?

javaenumscoding-styleverbose

提问by ByeBye

I have an enum:

我有一个枚举:

public enum Persons {

    CHILD,
    PARENT,
    GRANDPARENT;

}

Is there any problem with using ordinal()method to check "hierarchy" between enum members? I mean - is there any disadvantages when using it excluding verbosity, when somebody can change accidentally order in future.

使用ordinal()方法检查枚举成员之间的“层次结构”有什么问题吗?我的意思是 - 使用它时是否有任何缺点,不包括冗长,将来有人可能会意外更改顺序。

Or is it better to do something like that:

或者最好做这样的事情:

public enum Persons {

    CHILD(0),
    PARENT(1),
    GRANDPARENT(2);

    private Integer hierarchy;

    private Persons(final Integer hierarchy) {
        this.hierarchy = hierarchy;
    }

    public Integer getHierarchy() {
        return hierarchy;
    }

}

采纳答案by vikingsteve

TLDR: No, you should not!

TLDR:不,你不应该!

If you refer to the javadoc for ordinalmethod in Enum.java:

如果您参考 javadoc 中的ordinal方法Enum.java

Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as java.util.EnumSetand java.util.EnumMap.

大多数程序员不会使用这种方法。它设计用于复杂的基于枚举的数据结构,例如java.util.EnumSetjava.util.EnumMap

Firstly - read the manual (javadoc in this case).

首先 - 阅读手册(在这种情况下为 javadoc)。

Secondly - don't write brittle code. The enum values may change in future and your second code example is much more clearand maintainable.

其次 - 不要编写脆弱的代码。枚举值将来可能会发生变化,您的第二个代码示例更加清晰和易于维护

You definitely don't want to create problems for the future if a new enum value is (say) inserted between PARENTand GRANDPARENT.

如果在PARENT和之间插入(例如)新的枚举值,您绝对不想为将来制造问题GRANDPARENT

回答by gpeche

I would use your second option (using a explicit integer) so the numeric values are assigned by you and not by Java.

我将使用您的第二个选项(使用显式整数),因此数值由您而不是 Java 分配。

回答by davidxxx

The first way is not straight understandableas you have to read the code where the enums are used to understand that the order of the enum matters.
It is very error prone.

第一种方法不是直接可以理解的,因为您必须阅读使用枚举的代码才能理解枚举的顺序很重要。
它非常容易出错。

public enum Persons {

    CHILD,
    PARENT,
    GRANDPARENT;

}

The second wayis better as it is self explanatory:

第二种方法更好,因为它是不言自明的

CHILD(0),
PARENT(1),
GRANDPARENT(2);

private SourceType(final Integer hierarchy) {
    this.hierarchy = hierarchy;
}


Of course, orders of the enum values should be consistent with the hierarchical order provided by the enum constructor arguments.

当然,枚举值的顺序应该与枚举构造函数参数提供的层次顺序一致。

It introduces a kind of redundancyas both the enum values and the arguments of the enum constructor conveys the hierarchy of them.
But why would it be a problem ?
Enums are designed to represent constant and not frequently changing values.
The OP enum usage illustrates well a good enum usage :

它引入了一种冗余,因为枚举值和枚举构造函数的参数都传达了它们的层次结构。
但是为什么会有问题呢?
枚举旨在表示常量而不是经常变化的值
OP 枚举用法很好地说明了一个很好的枚举用法:

CHILD, PARENT, GRANDPARENT

Enums are not designed to represent values that moves frequently.
In this case, using enums is probably not the best choice as it may breaks frequently the client code that uses it and besides it forces to recompile, repackage and redeploy the application at each time an enum value is modified.

枚举并非旨在表示频繁移动的值。
在这种情况下,使用枚举可能不是最佳选择,因为它可能会频繁破坏使用它的客户端代码,此外,每次修改枚举值时,它都会强制重新编译、重新打包和重新部署应用程序。

回答by Leonardo Pina

Using ordinal()is unrecommended as changes in the enum's declaration may impact the ordinal values.

ordinal()不推荐使用,因为枚举声明中的更改可能会影响序数值。

UPDATE:

更新:

It is worth noting that the enum fields are constants and can have duplicated values, i.e.

值得注意的是,枚举字段是常量,可以有重复的值,即

enum Family {
    OFFSPRING(0),
    PARENT(1),
    GRANDPARENT(2),
    SIBLING(3),
    COUSING(4),
    UNCLE(4),
    AUNT(4);

    private final int hierarchy;

    private Family(int hierarchy) {
        this.hierarchy = hierarchy;
    }

    public int getHierarchy() {
        return hierarchy;
    }
}

Depending on what you're planning to do with hierarchythis could either be damaging or beneficial.

这取决于您打算做什么,hierarchy这可能是有害的,也可能是有益的。

Furthermore, you could use the enum constants to build your very own EnumFlagsinstead of using EnumSet, for example

此外,您可以使用枚举常量来构建您自己的EnumFlags而不是使用EnumSet,例如

回答by gati sahu

According to java doc

根据java文档

Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap.

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

You can control the ordinal by changing the order of the enum, but you cannot set it explicitly.One workaround is to provide an extra method in your enum for the number you want.

您可以通过更改枚举的顺序来控制序数,但不能显式设置它。一种解决方法是在您的枚举中为您想要的数字提供一个额外的方法。

enum Mobile {
   Samsung(400), Nokia(250),Motorola(325);

   private final int val;
  private Mobile (int v) { val = v; }
  public int getVal() { return val; }
}

In this situation Samsung.ordinal() = 0, but Samsung.getVal() = 400.

在这种情况下Samsung.ordinal() = 0,可是Samsung.getVal() = 400

回答by David Moles

First, you probably don't even need a numeric order value -- that's what Comparableis for, and Enum<E>implements Comparable<E>.

首先,您可能甚至不需要数字顺序值——这Comparable就是用于并Enum<E>实现Comparable<E>.

If you doneed a numeric order value for some reason, yes, you should use ordinal(). That's what it's for.

如果出于某种原因确实需要数字顺序值,是的,您应该使用ordinal(). 这就是它的用途。

Standard practice for Java Enumsis to sort by declaration order, which is why Enum<E>implements Comparable<E>and why Enum.compareTo()is final.

Java 的标准做法Enums是按声明顺序排序,这就是为什么要Enum<E>实现Comparable<E>,为什么 Enum.compareTo()final.

If you add your own non-standard comparison code that doesn't use Comparableand doesn't depend on the declaration order, you're just going to confuse anyone else who tries to use your code, including your own future self. No one is going to expect that code to exist; they're going to expect Enumto be Enum.

如果您添加自己的不使用Comparable且不依赖于声明顺序的非标准比较代码 ,您只会混淆试图使用您代码的任何其他人,包括您未来的自己。没有人会期望代码存在;他们会期望EnumEnum

If the custom order doesn't match the declaration order, anyone looking at the declaration is going to be confused. If it does(happen to, at this moment) match the declaration order, anyone looking at it is going to come to expect that, and they're going to get a nasty shock when at some future date it doesn't. (If you write code (or tests) to ensurethat the custom order matches the declaration order, you're just reinforcing how unnecessary it is.)

如果自定义顺序与声明顺序不匹配,任何查看声明的人都会感到困惑。如果它确实(此时恰好)与声明顺序匹配,那么任何查看它的人都会期待这一点,而在未来某个日期它不匹配时,他们将受到严重的冲击。(如果您编写代码(或测试)以确保自定义顺序与声明顺序匹配,那么您只是在强调它是多么不必要。)

If you add your own order value, you're creating maintenance headaches for yourself:

如果您添加自己的订单价值,则会为自己带来维护难题:

  1. you need to make sure your hierarchyvalues are unique
  2. if you add a value in the middle, you need to renumber all subsequent values
  1. 你需要确保你的hierarchy价值观是独一无二的
  2. 如果在中间添加一个值,则需要对所有后续值重新编号

If you're worried someone could change the order accidentally in the future, write a unit test that checks the order.

如果您担心将来有人可能会意外更改订单,请编写一个单元测试来检查订单。

In sum, in the immortal words of Item 47: know and use the libraries.

总之,用条款47的不朽的话来说: 了解和使用库



P.S. Also, don't use Integerwhen you mean int.

PS另外,Integer当你的意思是不要使用int

回答by Daniel Pryden

If you only want to create relationships between enum values, you can actually use the trick of using other enum values:

如果您只想在枚举值之间创建关系,您实际上可以使用使用其他枚举值的技巧:

public enum Person {
  GRANDPARENT(null),
  PARENT(GRANDPARENT),
  CHILD(PARENT);

  private final Person parent;

  private Person(Person parent) {
    this.parent = parent;
  }

  public final Parent getParent() {
    return parent;
  }
}

Note that you can only use enum values that were declared lexically before the one you're trying to declare, so this only works if your relationships form an acyclic directed graph (and the order you declare them is a valid topological sort).

请注意,您只能使用在您尝试声明之前在词法上声明的枚举值,因此这仅在您的关系形成无环有向图(并且您声明它们的顺序是有效的拓扑排序)时才有效。

回答by msf1013

As suggested by Joshua Bloch in Effective Java, it's not a good idea to derive a value associated with an enum from its ordinal, because changes to the ordering of the enum values might break the logic you encoded.

正如 Joshua Bloch 在Effective Java 中所建议的那样,从枚举值的序数派生出与枚举关联的值并不是一个好主意,因为对枚举值排序的更改可能会破坏您编码的逻辑。

The second approach you mention follows exactly what the author proposes, which is storing the value in a separate field.

您提到的第二种方法完全遵循作者的建议,即将值存储在单独的字段中。

I would say that the alternative you suggested is definitely better because it is more extendable and maintainable, as you are decoupling the ordering of the enum values and the notion of hierarchy.

我会说您建议的替代方案肯定更好,因为它更易于扩展和维护,因为您正在将枚举值的排序和层次结构的概念解耦。

回答by mzmrk

This is not a direct answer to your question. Rather better approach for your usecase. This way makes sure that next developer will explicitly know that values assigned to properties should not be changed.

这不是对您问题的直接回答。更适合您的用例的方法。这种方式确保下一个开发人员将明确知道分配给属性的值不应更改。

Create a class with static properites which will simulate your enum:

创建一个具有静态属性的类,它将模拟您的枚举:

public class Persons {
    final public static int CHILD = 0;
    final public static int PARENT = 1;
    final public static int GRANDPARENT = 2;
}

Then use just like enum:

然后像枚举一样使用:

Persons.CHILD

It will work for most simple use cases. Otherwise you might be missing on options like valueOf(), EnumSet, EnumMapor values().

它适用于大多数简单的用例。否则,您可能会缺少valueOf()EnumSetEnumMapvalues()等选项。