What is an efficient way to implement a singleton design pattern in Java?
Eager initialization: In eager initialization, the instance of Singleton Class is created at the time of class loading, this is the easiest method to create a Singleton class. By making the constructor as private you are not allowing other class to create a new instance of the class you want to create the Singleton.
Marking the class sealed prevents someone from trivially working around your carefully-constructed singleton class because it keeps someone from inheriting from the class.
There are two forms of singleton design pattern, which are: Early Instantiation: The object creation takes place at the load time. Lazy Instantiation: The object creation is done according to the requirement.
Definition: The singleton pattern is a design pattern that restricts the instantiation of a class to one object. Let's see various design options for implementing such a class. If you have a good handle on static class variables and access modifiers this should not be a difficult task.
Use an enum:
public enum Foo { INSTANCE; }
Joshua Bloch explained this approach in his Effective Java Reloaded talk at Google I/O 2008: link to video. Also see slides 30-32 of his presentation (effective_java_reloaded.pdf):
The Right Way to Implement a Serializable Singleton
public enum Elvis { INSTANCE; private final String[] favoriteSongs = { "Hound Dog", "Heartbreak Hotel" }; public void printFavorites() { System.out.println(Arrays.toString(favoriteSongs)); } }
Edit: An online portion of "Effective Java" says:
"This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton."
Depending on the usage, there are several "correct" answers.
Since Java 5, the best way to do it is to use an enum:
public enum Foo { INSTANCE; }
Pre Java 5, the most simple case is:
public final class Foo { private static final Foo INSTANCE = new Foo(); private Foo() { if (INSTANCE != null) { throw new IllegalStateException("Already instantiated"); } } public static Foo getInstance() { return INSTANCE; } public Object clone() throws CloneNotSupportedException{ throw new CloneNotSupportedException("Cannot clone instance of this class"); } }
Let's go over the code. First, you want the class to be final. In this case, I've used the final
keyword to let the users know it is final. Then you need to make the constructor private to prevent users to create their own Foo. Throwing an exception from the constructor prevents users to use reflection to create a second Foo. Then you create a private static final Foo
field to hold the only instance, and a public static Foo getInstance()
method to return it. The Java specification makes sure that the constructor is only called when the class is first used.
When you have a very large object or heavy construction code and also have other accessible static methods or fields that might be used before an instance is needed, then and only then you need to use lazy initialization.
You can use a private static class
to load the instance. The code would then look like:
public final class Foo { private static class FooLoader { private static final Foo INSTANCE = new Foo(); } private Foo() { if (FooLoader.INSTANCE != null) { throw new IllegalStateException("Already instantiated"); } } public static Foo getInstance() { return FooLoader.INSTANCE; } }
Since the line private static final Foo INSTANCE = new Foo();
is only executed when the class FooLoader is actually used, this takes care of the lazy instantiation, and is it guaranteed to be thread safe.
When you also want to be able to serialize your object you need to make sure that deserialization won't create a copy.
public final class Foo implements Serializable { private static final long serialVersionUID = 1L; private static class FooLoader { private static final Foo INSTANCE = new Foo(); } private Foo() { if (FooLoader.INSTANCE != null) { throw new IllegalStateException("Already instantiated"); } } public static Foo getInstance() { return FooLoader.INSTANCE; } @SuppressWarnings("unused") private Foo readResolve() { return FooLoader.INSTANCE; } }
The method readResolve()
will make sure the only instance will be returned, even when the object was serialized in a previous run of your program.
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