To avoid magic numbers, I always use constants in my code. Back in the old days we used to define constant sets in a methodless interface which has now become an antipatter
Using interfaces for storing constants is some kind of abusing interfaces.
But using Enums is not the best way for each situation. Often a plain int
or whatever else constant is sufficient. Defining own class instances ("type-safe enums") are even more flexible, for example:
public abstract class MyConst {
public static final MyConst FOO = new MyConst("foo") {
public void doSomething() {
...
}
};
public static final MyConst BAR = new MyConst("bar") {
public void doSomething() {
...
}
};
protected abstract void doSomething();
private final String id;
private MyConst(String id) {
this.id = id;
}
public String toString() {
return id;
}
...
}
Yes it is. Enum is the best choice.
You are getting for free:
All in one.
But wait, there's some more. Every enum value can have its own fields and methods. It's a rich constant object with behavior that allows transformation into different forms. Not only toString, but toInt, toWhateverDestination you need.
Enum is best for most of the case, but not everything. Some might be better put like before, that is in a special class with public static constants.
Example where enum is not the best solution is for mathematical constants, like PI. Creating an enum for that will make the code worse.
enum MathConstants {
PI(3.14);
double a;
MathConstants(double a) {
this.a = a;
}
double getValueA() {
return a;
}
}
Usage:
MathConstants.PI.getValueA();
Ugly isn't it? Compare to:
MathConstants.PI;
Forget about enums - now, when static import is available in Java, put all your constants in REAL class (instead of interface) and then just import the static members from all the other ones using import static <Package or Class>
.
For magic numbers where the number actual has a meaning and is not just a label you obviously should not use enums. Then the old style is still the best.
public static final int PAGE_SIZE = 300;
When you are just labelling something you would use an enum.
enum Drink_Size
{
TALL,
GRANDE,
VENTI;
}
Sometimes it makes sense to put all your global constants in their own class, but I prefer to put them in the class that they are most closely tied to. That is not always easy to determine, but at the end of the day the most important thing is that your code works :)