This question already has an answer here:
I was trying to understand how Java enum really works and I have come to the conclusion that it is very similar to a normal Java class that has its constructor declared private.
I have just come to this conclusion and it isn't based on much thinking, but Id like to know whether I miss anything.
So below is an implementation of a simple Java enum and an equivalent Java class.
public enum Direction {
ENUM_UP(0, -1),
ENUM_DOWN(0, 1),
ENUM_RIGHT(1, 0),
ENUM_LEFT(-1, 0);
private int x;
private int y;
private Direction(int x, int y){
this.x = x;
this.y = y;
}
public int getEnumX(){
return x;
}
public int getEnumY(){
return y;
}
}
What is the difference in meaning between the code above and below?
public class Direction{
public static final Direction UP = new Direction(0, -1) ;
public static final Direction DOWN = new Direction(0, 1) ;
public static final Direction LEFT = new Direction(-1, 0) ;
public static final Direction RIGHT = new Direction(1, 0) ;
private int x ;
private int y ;
private Direction(int x, int y){
this.x = x ;
this.y = y ;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
}
Take a look at this blogpage, it describes how Java
enum
s are compiled into bytecode. You'll see that there's a small addition compared to your second code sample, which is an array ofDirection
objects calledVALUES
. This array holds all possible values for your enum, so you won't be able to do(for example using reflection) and then use that as a valid
Direction
value.Plus, as @Eng.Fouad correctly explains, you don't have
values()
,valueOf()
andordinal()
.The main difference is the each
enum
class implicitly extendsEnum<E extends Enum<E>>
class. This leads to that:enum
objects have such methods asname()
andordinal()
enum
objects have specialtoString()
,hashCode()
,equals()
andcompareTo()
implementationsenum
objects are suitable forswitch
operator.All mentioned above is not applicable for your version of
Direction
class. This is the "meaning" difference.Differences:
java.lang.Enum
and gain all of its nice features:.toString
method on enum values without the need to duplicate your enum names.name
and.ordinal
special-purpose methodsEnumSet
andEnumMap
classespublic static final
fieldsswitch
statementspublic static (Enum)[] values();
public static (Enum) valueOf(java.lang.String);
private static final (Enum)[] $VALUES;
(values()
returns a clone of this)Most of these can be emulated with a suitably designed class, but
Enum
just makes it really easy to create a class with this set of particularly desirable properties.As people have pointed out you lose
values()
,valueOf()
andordinal()
. You can replicate this behaviour fairly easily using a combination of aMap
and aList
.As you can see; the code becomes very clunky very quickly.
I'm not sure if there is a way for replicate a
switch
statement with this class; so you will lose that.To answer the question: essentially, there's no difference between the two approaches. However, enum construct provides you with some additional supporting methods like
values()
,valueOf()
, etc. which you'd have to write on your own with the class-with-private-constructor approach.But yeah, I like how Java enums are mostly just like any other classes in Java, they can have fields, behaviors, etc. But to me what separates enums from the plain classes is the idea that enums are classes/types whose instances/members are predetermined. Unlike usual classes where you can create any number of instances from, enums only limit creation to known instances. Yes, as you've illustrated, you can also do this with classes with private constructors, but enums just make this more intuitive.