What is the proper way to initialize java enum based singleton, if I have to initialize it before I can use the object.
I have started writing the code , but I am not sure if I am doing it right. Could you help me to implement this singleton correct for me?
public enum BitCheck {
INSTANCE;
private static HashMap<String, String> props = null;
public synchronized void initialize(HashMap<String, String> properties) {
if(props == null) {
props = properties;
}
}
public boolean isAenabled(){
return "Y".equalsIgnoreCase(props.get("A_ENABLED"));
}
public boolean isBenabled(){
return "Y".equalsIgnoreCase(props.get("B_ENABLED"));
}
}
-
I don't like this, what are you trying to achieve?zengr– zengr2012年10月02日 20:31:34 +00:00Commented Oct 2, 2012 at 20:31
-
Why do you need an enum with only one element when you are already using a singleton?Dunes– Dunes2012年10月02日 20:44:28 +00:00Commented Oct 2, 2012 at 20:44
-
@Dunes I want a singleton so that I can use this throughout my code base to check values. I will initialize with the properties during startup and will use the check methods all over the project.java_mouse– java_mouse2012年10月02日 20:45:49 +00:00Commented Oct 2, 2012 at 20:45
-
1I understand why you might want a singleton, but to also make it an enum seems bizarre.Dunes– Dunes2012年10月02日 20:48:08 +00:00Commented Oct 2, 2012 at 20:48
-
9@Dunes Please read this SO question for some enlightenment regarding using Enums as Singletons: What is an efficient way to implement a singleton pattern in Java?.maba– maba2012年10月03日 10:42:54 +00:00Commented Oct 3, 2012 at 10:42
6 Answers 6
It's perfectly possible to create constructor for enum
:
public enum BitCheck {
INSTANCE;
BitCheck() {
props = new HashMap<String, String>();
}
private final Map<String, String> props;
//..
}
Note that:
props
field can be final (we likefinal
)props
doesn't have to bestatic
- constructor is called automatically and eagerly for you
Pay attention to the last point. Since enum
-singletons are created eagerly when the enum BitCheck
class is loaded, you have no way to pass any arguments to the constructor. Of course you can through INSTANCE
declaration:
public enum BitCheck {
INSTANCE(new HashMap<String, String>());
BitCheck(final Map<String, String> props) {
this.props = props;
}
but this doesn't make any difference, right? What do you want to achieve? Maybe you actually need lazy-initialized singleton?
4 Comments
enum
singleton won't help you.You have to just initialize it in declaration.
public enum BitCheck {
INSTANCE;
private final Map<String, String> props = new ConcurrentHashMap<String, String>();
public void putAll(HashMap<String, String> map) {
props.putAll(map);
}
}
Comments
You need to define a constructor like this:
public enum BitCheck {
INSTANCE;
private final HashMap<String, String> props;
BitCheck() {
}
}
A very good example is the Planet enum at: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
Comments
public enum BitCheck {
INSTANCE;
private BitCheck() {
// initialize here
}
}
Comments
You should implement to interfaces and therefore change to:
private Map<...> props;
You can look at What is the best approach for using an Enum as a singleton in Java? which is similar to what you want.
Comments
You can try something like this within your Enum based singleton code. This will make sure that the Singleton can be initialized exactly once.
private static Properties props;
private static AtomicBoolean isInitialized = new AtomicBoolean(false);
public void init(Properties props){
if(isInitialized.compareAndSet(false, true)) {
this.props = props;
}
}
NOTE: For more complex initialization, you would need 2 AtomicBooleans for initStarted and initCompleted (instead of single AtomicBoolean - isInitialized). Then the first thread sets initStarted and executes the initialization steps, the rest wait until initCompleted is set to true by first thread.