Do you think your Singleton Class in Java is working the way it should? What if it is not safe or can cause problems in your program? The Singleton Class is a popular way in Java to make sure only one object of a class is created. It sounds simple, but many people get it wrong. Some ways of doing it can cause errors.
In this article, we will explain what the Singleton Class is in Java, different ways to use it, and which one is best for your code with easy examples and steps.
Table of Contents:
Singleton Class in Java
A singleton class is a class in Java that has only one object throughout its lifetime in the JVM. It provides a global point of access, i.e., this class can be accessed from anywhere in the application by using a static or by .getInstance(); method like:
Singleton obj = Singleton.getInstance();
Example:
Consider a class A as a singleton.
A one = A.getInstance();
A two = A.getInstance();
In the above case, both objects one and two point to the same memory location.
Master Java Today - Accelerate Your Future
Enroll Now and Transform Your Future
Example of a Singleton Class in Java
1. Singleton.java
2. Main.java
Output:
Explanation: In the above Java code, private Singleton() is used so that no new instance is made, and when the objects o1 and o2 are made, they directly point to the same memory location. When the objects are compared, the output becomes true.
Singleton Pattern Principles
The following are the principles of the Singleton class:
1. It restricts the instantiation of a class, which means you can’t create many objects from the class. Only one object is made for the whole program. This is helpful when you need a single, shared resource.
For example, think of a company in which there is only one manager, and everyone talks to the manager about important work.
2. It provides a Global Access Point, which means that any part of the program can call this method to get the same single object.
For example, you have a public phone number to reach the same person from anywhere.
3. It ensures that only one object of the class manages all the operations, due to which the object is not created every time a new resource is needed.
- Logging: You only need one logger to track app activity.
- Database drivers: One shared connection or configuration.
- Caching: Store and reuse data in one place.
- Thread pool: Reuse a fixed set of threads instead of creating new ones each time.
4. It is used in Other Design Patterns like Abstract Factory, Builder, Prototype, and Facade.
These patterns need a shared manager or a central object, for which a singleton is used.
5. It is used in Core Java Classes.
For Example:
1. java.lang.Runtime: Used to interact with the Java environment
Runtime runtime = Runtime.getRuntime();
2. java.awt.Desktop: Used to open files, web pages, etc.
Desktop desktop = Desktop.getDesktop();
How to Implement the Singleton Class in Java?
There are three core concepts to implement the Singleton class in Java. These are as follows.
- A private constructor is used so that no outside class can make an object of the singleton class using the new keyword. As the constructor will be private, no other class can do it.
Singleton obj = new Singleton();
- Private static variables are used so that the variables belong to the class only, not to their objects.
- Public Static Method is used so that there is only one way for the other classes to get the Singleton object. Also, it returns a single instance.
Ways to Implement the Singleton Class in Java
There are many ways to implement the Singleton class in Java. Some of them are as follows:
1. Eager Initialization (Thread-safe by default)
In this method, the Singleton object is created as soon as the class is loaded. It is simple to use.
The instance is created when the class is loaded, hence, it offers thread safety. But, sometimes, even if the object is never used, its instance is created.
Example:
Output:
Explanation: In the above Java code, the object of the class is made as soon as it is loaded in the memory, using the static final variable.
2. Lazy Initialization (Not Thread-safe)
In this method, the object is only created when it is needed, which saves memory of the resources. But this method is not safe, as two threads can create two instances at the same time. This version is not thread-safe and should not be used in multi-threaded applications. This method is safe for single-threaded environments
Example:
Output:
Explanation: In the above Java code, the object of the class is made only when the getInstance() method is called.
3. Thread-Safe Singleton (Synchronized Method)
To make the above approach thread-safe, the synchronized method is used inside the getInstance() method. When a thread enters the synchronized method, it locks the class on the class object. It also ensures that only one object is made, even in a multi-threaded environment. It slows down the performance, as the synchronization locks the method.
If the whole method is being synchronized, it can lead to performance issues.
Example:
Output:
Explanation: In the above Java code, the getInstance() method is used with a synchronized block so that the thread remains safe.
This method improves the performance by using the synchronized block when the instance is null. It also double-checks if the instance is created. It uses the volatile keyword to ensure that changes made in the instance variable are immediately visible to the other threads. It makes the code complex.
Example:
Output:
Explanation: In the above Java code, the instance is checked twice before and after the synchronized block. Also, the volatile keyword is used to check the thread visibility in the program.
Get 100% Hike!
Master Most in Demand Skills Now!
5. Bill Pugh Singleton Design (Best Approach)
This is considered the best method to implement a Singleton in Java. It uses the Java class loader mechanism to maintain thread-safety. It is a simple and efficient approach. This approach ensures lazy initialization without synchronization overhead.
Example:
Output:
Explanation: In the above Java code, the instance is only made when the getInstance() method is called. It uses a static inner class inside which the object is created.
6. Enum Singleton (Recommended for Simplicity)
This method is thread-safe and performs the serialization automatically. It cannot be inherited from another class.
It is considered one of the best ways to implement singletons in Java due to its serialization and reflection safety. However, it is not used by built-in singletons like Runtime, which instead uses eager initialization with a static final field.
Example:
Output:
Explanation: The above Java code uses an enum with a single constant to create a Singleton object.
7. Static Block Initialization
This method is similar to eager initialization, but the object here is created in the static block. It also handles the exceptions during the creation of the object.
Example:
Output:
Explanation: In the above Java code, the object is created inside a static block when the class is loaded into memory.
8. Using reflection
Reflection allows us to change the classes, methods, and constructors at runtime, even if they are private. It can also bypass access control, which makes it possible to create a second instance of a Singleton class, even if the constructor is private. To prevent this, throw an exception if the constructor is called a second time.
Example:
Output:
Explanation: In the above Java code, the private constructor is accessed with the help of reflection. After which the two objects created are compared to each other, which return false, as they both are not same.
When To Use a Singleton Class And When To Avoid It?
The Singleton class in Java should be used when you want only one object of the class throughout your program lifecycle. It helps in managing the resources of the computer, like database connections. It also ensures that all the resources are accessed easily.
However, they should be avoided when they are not used, as they can make your code complicated. They should be avoided when they can lead to a global state, or if they are making the unity testing more complex.
Pros of the Singleton Class
- Only one instance is created.
- It saves memory by not creating multiple objects.
- It is useful for shared resources (e.g., logging, config, cache, DB, etc).
- It is easy to implement and understand.
- Thread-safe variants are available.
- Can be lazy-loaded if required.
Cons of the Singleton Class
- It can be broken using reflection, serialization, or cloning.
- It makes unit testing difficult due to the global state.
- It has a global state, which can lead to hidden dependencies.
- It is not suitable for all use cases, especially when different states are needed.
- It is difficult to subclass (due to the private constructor).
- It can lead to tight coupling.
Unlock Your Future in Java
Start Your Java Journey for Free Today
Conclusion
The Singleton Class in Java ensures that only one object is created and used throughout the program. There are different ways to do this, like eager or lazy initialization, double-checked locking, the Bill Pugh method, and using an enum. Each method has its own benefits and drawbacks. The enum method is the safest, especially for handling special cases like serialization and reflection. It also prevents reflection-based breaking.
If you want to learn more about Java, you can refer to our Java Course.
Singleton Class in Java – FAQs
Q1. How many ways to break a singleton class in Java?
There are several ways to break the singleton pattern in Java, including reflection, serialization/deserialization, cloning, multi-threading, multiple class loaders, and garbage collection.
Q2. Why use volatile in Singleton?
The volatile keyword ensures that any changes made to the instance variable are immediately visible to all threads, preventing any caching issues.
Q3. Can we create more than one object in the Singleton class?
No, we cannot create more than one object in the Singleton class.
Q4. What is lazy and eager initialization in a singleton?
An Eager Singleton creates an instance of the Singleton class as soon as the application starts, whereas a Lazy Singleton creates the instance only when it is needed.
Q5. How many ways are there to create an object in Java?
In Java, an object can be created in five main ways: using the new keyword, using Class.forName() method, using the clone() method, using the newInstance() method of the Constructor class, and through deserialization.