Is it good practice to use ordinal of enum?

2019-01-23 12:35发布

I have 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.

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;
    }

}

9条回答
疯言疯语
2楼-- · 2019-01-23 13:28

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

查看更多
Evening l夕情丶
3楼-- · 2019-01-23 13:30

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.

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.

查看更多
【Aperson】
4楼-- · 2019-01-23 13:39

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

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

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

If you add your own non-standard comparison code that doesn't use Comparable and 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 Enum to be Enum.

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 ensure that 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 hierarchy values are unique
  2. if you add a value in the middle, you need to renumber all subsequent values

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.


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

查看更多
登录 后发表回答