Reputation: 7569
I had the following field in my code:
private static final int NUM_NANOSECONDS_IN_MILLISECOND = 1000000;
I was told that I should be using an enum for this for type safety. This is not something I am familiar with. But if this is the case, I don't know when it would ever be appropriate to use the final keyword on a field.
When should I use the final keyword instead of enums?
Upvotes: 2
Views: 1845
Reputation: 21902
Constants are just that, constants with a name. Enums are literal constants that have a value. I explain...
Consider:
public final static int NORTH = 0;
public final static int SOUTH = 1;
public final static int EAST = 2;
public final static int WEST = 3;
and
public enum Direction {
NORTH, SOUTH, EAST, WEST
}
From a readability standpoint it kinda looks the same:
if(direction == NORTH)
or with enums:
if(direction == Direction.NORTH)
Where things might go wrong is that with the final constant, you can also do
if(direction == 0)
Now it's more difficult to understand the code even though it does the same thing. With enums, you just can't do that so it's let problems.
Similarly, when expecting a direction as a method argument:
with final static:
public void myMethod(int direction)
and with enums:
public void myMethod(Direction direction)
It's clearer, and less opportunities for problems.
This is just a beginning. Enums can actually have methods that help you better manage the information they contain. Read up here for a clean explanation.
Example:
public enum Direction {
NORTH (0, 1),
SOUTH (0, -1),
EAST (1, 0),
WEST (-1, 0)
private int xDirection, yDirection;
Direction(int x, int y) {
this.xDirection = x;
this.yDirection = y;
}
public Vector2D getTranslation() {
return new Vector2D(this.xDirection, this.yDirection);
}
}
So then in your code:
public void moveThePlayer(Player p, Direction d) {
p.translate(d.getTranslation());
}
moveThePlayer(p, Direction.NORTH);
This becomes really hard to do with final static
. Or at least, it gets very unreadable.
All this being said, with the particular case you are working with there, if there's only one numeric constant value, I'd keep the final static. No point using an enum if there's a single value.
Upvotes: 6
Reputation: 17593
When writing source code it is best to rely on the compiler as much as possible to help you find logic errors. One way is to use variable and constant types so that if you use the wrong constant for a method, the compiler will flag this as an error.
The advice is not really about using final
versus enum
since those are really two different programming concepts. It is instead using an enum
to create an explicit and unique type versus using an int
which is much less explicit and unique. If you use int
as part of the method signature for a function that is supposed to take nanoseconds then any int
value will be accepted by the compiler. If you instead use an enum
then only those values that are specified in the enum
are allowed. Using anything else will cause the compiler to issue an error.
The final
keyword is a way of making sure that the variable can not be overriden or modified so that the variable acts like a constant. wikipedia article on final.
The values specified in an enum
are constants so you can choose between using what you have, a constant, or using an enum
, a constant, however using the enum
will provide a safety check from the compiler so that only the specified values of the enum
can be used in a method call or variable assignment for nanoseconds.
Here is an explanation of final
with additional links from that stack overflow. Java method keyword final and its use also provides some additional information.
See What is the purpose of Enum for some explanation about enum
.
Upvotes: 1
Reputation: 81568
It honestly depends on what you need. enum
as its name shows stands for enumeration.
Enumerations have multiple elements like so
public enum Colors {
CYAN, MAGENTA, YELLOW, BLACK
}
You could even give them numerical values or so! Because enums are cool.
public enum RGBColors {
RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF);
private int hexacolor;
private RGBColors(int hexacolor) {
this.hexacolor = hexacolor;
}
public int getColorValue() {
return hexacolor;
}
}
Your case is just a numerical constant. A single numerical constant.
public static final long SUCH_NUMERICAL_VALUE = 12367160L;
This is just a constant. This is not an enumeration. There is also no reason for it to be an enumeration, as you are just using it as a number.
The biggest advantage (in my opinion) of an enum
is that you can iterate on every element of its type.
for(RGBColors rgbColor : RGBColors.values()) {
... //do things with rgbColor for each of them
}
You cannot do that with public static final int
. I even wrote an enum
wrapper around a bunch of public static final
properties here because of this problem: https://stackoverflow.com/a/28295134/2413303
More importantly, you can easily read what value stands for what without having to go deep into the source:
RGBColors red = RGBColors.RED;
Now let's see this with int:
int red = RGBColors.RED;
I could just say
int red = 0; //red color
Who will tell what on earth that is later? Who knows!
Anyways, the short answer is, enums are great when you're specifying enumerations, aka multiple elements (or you're creating enum singletons), and these elements need to have extra methods or properties.
public enum MySingleton { //this is an enum singleton
INSTANCE;
public void doThings() {
System.out.println("hello!");
}
}
MySingleton.INSTANCE.doThings(); //hello!
Constants (public static final
) are great when you use them as exactly that: constants.
Upvotes: 4
Reputation: 6675
I would say that the general use case for enums would be when you have a small finite set of values that form some set you are modeling and you are going to enumerate each one. They can also help ensure that a field that should contain one of these values does not contain some other value.
In this case, neither seems to apply. You could just as well have NUM_NANOSECONDS_IN_MICROSECOND
, NUM_NANOSECONDS_IN_SECOND
, NUM_NANOSECONDS_IN_PI_MILLISECONDS
, and so on, and you aren't going to enumerate each one. Furthermore, it would seem that the variables you are going to be storing these values in probably shouldn't be restricted to the values of the defined constants.
Upvotes: 3
Reputation: 48864
Using an enum avoids using an int
, not final
. Using a dedicated enum provides type safety, so you can have clearer method signatures and avoid bugs. final
is used to prevent changing a value once set, and is a generally good practice regardless of the variable's type.
In this case however I'm not sure what value an enum gives you. NUM_NANOSECONDS_IN_MILLISECOND
doesn't seem like it should be a dedicated type, and as @BoristheSpider suggests, you shouldn't need this field at all. Perhaps your associate was suggesting using an enum for the unit (e.g. NANOSECOND
, MILLISECOND
, etc) rather than storing ratios like this. In that case, the existing TimeUnit
enum is definitely your friend.
Upvotes: 6