The question of where to define constants in Java has appeared numerous times in forums, yet I am struggling to settle on a solution I feel comfortable with.
To make it simple, suppose I have two classes: WriteMyData
and ReadMyData
. None is a subclass of the other. Both classes share two constants that are vital for their operation: String DELIMITER
and int LENGTH
. In the future I might want to change the value of these constants so they should be defined somewhere appropriate.
The consensus seems to often favour the enum
type. However, there is nothing to enumerate in my case, so I end up with only one item in my enum
which I call DEFAULT
:
public enum DataSettings {
DEFAULT(",", 32);
private final String delimiter;
private final int length;
DataSettings(String delmiter, int length) {
this.delimiter = delimiter;
this.length = length;
}
public String getDelimiter() { return delimiter; }
public int getLength() { return length; }
}
Thus, in both my classes I access the constants through DataSettings.DEFAULT.getDelimiter()
and DataSettings.DEFAULT.getLength()
.
Is this really good OO style? Is the use of enum
perhaps overkill? If I do not use enum
, what should I do instead? Creating an interface for constants seems to be frowned upon, and there seems to be no natural superclass for my classes to derive from. Is it a beginners mistake to have only one default item in an enum
?
Just create something like Constants.java
class where you will put all the constants.
For example:
public class Constants {
public static final String DELIMITER = "-";
public static final int LENGTH = 1;
}
And use them where you want by:
Constants.DELIMITER
Constants.LENGTH
If only those two constans and not going to have more than that, You can have a Interface like
interface DataSetting
{
String DELIMITER = ",";
int LENGTH = 32;
}
And if you need to initilize through property
public class DataSetting {
public static String DELIMITER = ",";
public static int LENGTH = 32;
static {
DELIMITER = System.getProperty("delimiter");
LENGTH = Integer.parseInt(System.getProperty("length"));
// or from config
}
}
Using an enum
when there is nothing to enumerate is indeed bad practice.
The other mentioned alternative, using an interface
is also a poor choice. Effective Java, Item 19 describes it best:
Item19: Use interfaces only to define types
When a class implements an interface, the interface serves as a type that can be used to refer to instances of the class. That a class implements an interface should therefore say something about what a client can do with instances of the class. It is inappropriate to define an interface for any other purpose.
One kind of interface that fails this test is the so-called constant interface. Such an interface contains no methods; it consists solely of static final fields, each exporting a constant. Classes using these constants implement the interface to avoid the need to qualify constant names with a class name.
The correct implementation is to define a non-instantiable utility class:
public class Constants {
private Constants(){} // Private constructor prevents instantiation AND subclassing
public static final String DELIMITER = "-";
public static final int LENGTH = 1;
}
For convenience you can statically import the constants in your code:
import static com.example.Constants.*;
public class Test {
public static void main(String[] args){
System.out.println(DELIMITER); // prints "-"
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With