1. Introduction
In this article, We'll learn what is singleton pattern is in java and how to implement it. You will learn various ways to create singleton objects. This is the only design pattern that is used by every application in the software industry and also used extensively in java API such as Spring, apache or spark, etc. A question from the design pattern is a must in the interview and many questions come from this topic. This is my favourite interview question that I ask software developers. This question will check to understand many areas of core java such as private access modifier, static members, cloning, multithreading, deep cloning, serialization and deserialization and reflection api.
In this post, You will learn the frequently asked question on the singleton design pattern. If you are preparing for interviews, this will give you a clear picture of the singleton pattern.
2. Singleton Design Pattern Rules
Sington means always one object should exist in the entire life of an application at any time. If a class produces two objects or more then it is not a singleton pattern.
Let us understand the rules for the singleton pattern.
- First, need to make the constructor private so that object can not be created from any other class.
- Create, Static field referencing the same class object.
- Create a static method to get the singleton instance. This method will be invoked by other classes to get the singleton instance.
3. Singleton Design Pattern Creation
Creating a singleton class.package com.java.w3schools.blog.java.program.to.desingpatterns; public class SingletonPattern { // private static field. private static SingletonPattern instance; // private constructor private SingletonPattern() { } public static SingletonPattern getInstance() { if (instance == null) { instance = new SingletonPattern(); } return instance; } }
4. Singleton Design Pattern Verification
Created 3 singleton class objects in the below program. Printed all 3 objects and hashcodes as well.
package com.java.w3schools.blog.java.program.to.desingpatterns; public class SingletonPatternMain { public static void main(String[] args) { SingletonPattern object1 = SingletonPattern.getInstance(); SingletonPattern object2 = SingletonPattern.getInstance(); SingletonPattern object3 = SingletonPattern.getInstance(); System.out.println("object 1 " + object1); System.out.println("object 2 " + object2); System.out.println("object 3 " + object3); System.out.println("object 1 hashCode " + object1.hashCode()); System.out.println("object 2 hashCode " + object2.hashCode()); System.out.println("object 3 hashCode " + object3.hashCode()); } }
Output:
Observe the output and all objects are having the same memory address and hashcodes. So, It is creating always single objects.
If the above code is used in concurrent applications there might be a chance of creating multiple objects. To avoid duplicate objects creation, object creation logic should be surrounded by some special monitor. This object creation logic is called a critical section and this should be synchronized.
The above code is called single locking because only once if(instance == null) is checked.
The above code is still having the chance for multiple objects creation. To prevent this from multiple threads, double-checking logic should be used here.
Observe the output and all objects are having the same memory address and hashcodes. So, It is creating always single objects.
object 1 com.java.w3schools.blog.java.program.to.desingpatterns.SingletonPattern@4b1210ee object 2 com.java.w3schools.blog.java.program.to.desingpatterns.SingletonPattern@4b1210ee object 3 com.java.w3schools.blog.java.program.to.desingpatterns.SingletonPattern@4b1210ee object 1 hashCode 1259475182 object 2 hashCode 1259475182 object 3 hashCode 1259475182
5. Singleton Design Pattern In Multiple threads
If the above code is used in concurrent applications there might be a chance of creating multiple objects. To avoid duplicate objects creation, object creation logic should be surrounded by some special monitor. This object creation logic is called a critical section and this should be synchronized.
5.1 Synchronizing Critical Section
public static SingletonPattern getInstance() { if (instance == null) { synchronized (SingletonPattern.class) { instance = new SingletonPattern(); } } return instance; }
5.2 Double Checked Locking
The above code is still having the chance for multiple objects creation. To prevent this from multiple threads, double-checking logic should be used here.
// double locking pattern. public static SingletonPattern getInstance() { if (instance == null) { synchronized (SingletonPattern.class) { if (instance == null) { instance = new SingletonPattern(); } } } return instance; }
6. Creating Singleton with ENUM
Now, let us jump into another interesting way of creating singleton with Enum. This approach is safer from cloning, serialization and multiple threads.
public enum SingletonEnum { INSTANCE("enum singleton"); private String state; private SingletonEnum(String state) { this.state = state; } public SingletonEnum getInstance() { return INSTANCE; } public String getState() { return state; } public void setState(String state) { this.state = state; } }
Verification with Enum:
public enum SingletonEnum { INSTANCE("enum singleton"); private String state; private SingletonEnum(String state) { this.state = state; } public SingletonEnum getInstance() { return INSTANCE; } public String getState() { return state; } public void setState(String state) { this.state = state; } }
Output:
enum singleton instance : enum singleton enum singleton instance : enum singleton enum singleton instance : enum singleton
7. Singleton Breaking With Cloning
This is an interview question. If Singleton class implements Clonable interface and implemented clone() then it returns a new object each time clone() method is called.
package com.java.w3schools.blog.java.program.to.desingpatterns; public class SingletonPattern implements Cloneable{ // common doublechecking logic or normal singel ton code. @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); } }
Let us check the hashcodes of cloned objects.
SingletonPattern object4 = SingletonPattern.getInstance(); System.out.println("Object 4 hashcode : " + object4.hashCode()); SingletonPattern object5 = (SingletonPattern) object4.clone(); System.out.println("Object 5 hashcode : " + object5.hashCode()); SingletonPattern object6 = (SingletonPattern) object4.clone(); System.out.println("Object 6 hashcode : " + object6.hashCode());
Object 4 hashcode : 1259475182 Object 5 hashcode : 1300109446 Object 6 hashcode : 1020371697
How to prevent singleton from cloning?
Answer 1: Return the same singleton instance from the clone method.
@Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return instance; }
Answer 2: Throw exception saying clonenotsupportexception.
@Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException("Clone not supported for SingletonPattern class"); }
Note: But recommended is not to implement the clonable interface in singleton pattern.
8. Singleton Breaking With Deep Cloning or serialization
How do you prevent singleton from creating another new instance from serialization?
This is a great interview question but you should have a deep understanding of serialization. During the serialization, readObject() method is used to create the object and return a new instance every time with readResolve() method. To prevent creating a new object, just need to return the singleton instance from readResolve() method.
If you use Enum which is taken care of these by JVM.
9. Sington Breaking With Reflection API
How to prevent a singleton from creating another object from reflection api?
By using reflection api, We can change the constructor visibility to the public from private.
SingletonPattern object7 = SingletonPattern.getInstance(); System.out.println("Object 7 hashcode : " + object4.hashCode()); Constructorconstructor = SingletonPattern.class.getDeclaredConstructor(); constructor.setAccessible(true); SingletonPattern pattern = constructor.newInstance(); System.out.println("singeleton new object through reflection api : " + pattern.hashCode());
Object 4 hashcode : 1259475182 singeleton new object through reflection api : 1300109446
This can be avoided by throwing exceptions from the constructor if the singleton instance is not null.
// private constructor private SingletonPattern() { if (instance != null) { throw new RuntimeException("You can create new object."); } }
10. Java API Singleton Classes
What are the Java built-in Singleton classes in Java API?
Runtime, Toolkit and Desktop classes are singleton classes.
Java.lang.Runtime with getRuntime()
Java.awt.Toolkit with getDefaultToolkit()
Java.awt.Desktop with getDesktop()
11. Conclusion
In this article, we've seen what is singleton pattern and how to implement it? Frequently asked interview questions.
In conclusion, all examples are shown in this article are in GitHub
GitHub Code
No comments:
Post a Comment
Please do not add any spam links in the comments section.