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"));
    }

}
java_mouse
  • 2,069
  • 4
  • 21
  • 30
  • I don't like this, what are you trying to achieve? – zengr Oct 02 '12 at 20:31
  • Why do you need an enum with only one element when you are already using a singleton? – Dunes Oct 02 '12 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 Oct 02 '12 at 20:45
  • 1
    I understand why you might want a singleton, but to also make it an enum seems bizarre. – Dunes Oct 02 '12 at 20:48
  • @Dunes Thanks. I understand. What you are saying is , I should implement a regular singleton instead of using "Enum"?? – java_mouse Oct 02 '12 at 20:49
  • Pretty much. Enums and Singletons are pretty much the antithesis of each other. Enums are designed to have multiple elements. For instance, they implement the Comparable interface and there is a specialised `Set` and `Map` class just for enums -- things you have absolutely no need for with a singleton. – Dunes Oct 02 '12 at 20:57
  • 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?](http://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java). – maba Oct 03 '12 at 10:42

6 Answers6

37

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?

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • I guess It will be bad Idea to create like this since constructor does not offer anything good. It can be simple declaration – Amit Deshpande Oct 02 '12 at 20:42
  • 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 Oct 02 '12 at 20:43
  • 2
    @java_mouse: that's the thing. There is no way to pass anything to the constructor from outside, `enum` singleton won't help you. – Tomasz Nurkiewicz Oct 02 '12 at 20:45
  • @TomaszNurkiewicz Thanks, I think I got it. I should go for traditional singleton implementation. – java_mouse Oct 02 '12 at 20:50
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);
    }
}
Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
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,548
  • 31
  • 45
Jordan Denison
  • 2,649
  • 14
  • 14
1
public enum BitCheck {

    INSTANCE;

    private BitCheck() {
        // initialize here
    }

}
devang
  • 5,376
  • 7
  • 34
  • 49
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.

Community
  • 1
  • 1
ramsinb
  • 1,985
  • 12
  • 17
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.

janeshs
  • 793
  • 2
  • 12
  • 26
  • 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. – Debajyoti Pathak Nov 03 '19 at 16:22