20

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"));
 }
}
asked Oct 2, 2012 at 20:25
7
  • I don't like this, what are you trying to achieve? Commented Oct 2, 2012 at 20:31
  • Why do you need an enum with only one element when you are already using a singleton? Commented 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. Commented Oct 2, 2012 at 20:45
  • 1
    I understand why you might want a singleton, but to also make it an enum seems bizarre. Commented 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?. Commented Oct 3, 2012 at 10:42

6 Answers 6

38

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 like final)
  • props doesn't have to be static
  • 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?

answered Oct 2, 2012 at 20:34

4 Comments

I guess It will be bad Idea to create like this since constructor does not offer anything good. It can be simple declaration
I want to initialize with a set of values, that I want to pass it to the singleton. How can I do that? Your example is initializing with empty hashmap.
@java_mouse: that's the thing. There is no way to pass anything to the constructor from outside, enum singleton won't help you.
@TomaszNurkiewicz Thanks, I think I got it. I should go for traditional singleton implementation.
6

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);
 }
}
answered Oct 2, 2012 at 20:39

Comments

2

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

Ben
7,59533 silver badges46 bronze badges
answered Oct 2, 2012 at 20:35

Comments

1
public enum BitCheck {
 INSTANCE;
 private BitCheck() {
 // initialize here
 }
}
answered Oct 2, 2012 at 20:36

Comments

1

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.

answered Oct 2, 2012 at 20:38

Comments

0

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.

answered Jun 20, 2016 at 11:19

1 Comment

Not sure what exactly you mean by complex initialization and why would we need 2 atomic booleans. Correct me if I am wrong, but I think your above code should work fine as long as I have all the initialization code (however many steps) within that 'if' block.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.