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;
}
}
If you refer to the javadoc for ordinal
method in 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.EnumSet
and java.util.EnumMap
.
Firstly - read the manual (javadoc in this case).
Secondly - don't write brittle code. The enum values may change in future and your second code example is much more clear and maintainable.
You definitely don't want to create problems for the future if a new enum value is (say) inserted between PARENT
and GRANDPARENT
.
The first way is not straight understandable as 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 way is 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 redundancy as 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 :
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.
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:
- you need to make sure your
hierarchy
values are unique
- 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
.