How to Create a Singleton Class in Java ?

In Java, a singleton class is a class that allows only one instance of itself to be created and provides a global access point to that instance. Singleton patterns are often used in cases where a single shared resource, like a configuration manager or database connection pool, needs to be globally accessible.

Here’s how to create a singleton class in Java, including the commonly used “lazy initialization” and “eager initialization” methods.

1. Eager Initialization Singleton

In eager initialization, the singleton instance is created when the class is loaded. This is the simplest approach and is thread-safe without requiring synchronization.

public class SingletonEager {
    // Create the singleton instance when the class is loaded
    private static final SingletonEager instance = new SingletonEager();

    // Private constructor prevents instantiation from other classes
    private SingletonEager() {}

    // Public method to provide access to the instance
    public static SingletonEager getInstance() {
        return instance;
    }
}

2. Lazy Initialization Singleton

In lazy initialization, the singleton instance is created only when it’s needed. This can save resources if the instance is not always required, but it requires synchronization to make it thread-safe.

public class SingletonLazy {
    // Instance is not created initially
    private static SingletonLazy instance;

    // Private constructor prevents instantiation from other classes
    private SingletonLazy() {}

    // Public method to provide access to the instance, with synchronized access
    public static synchronized SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}

3. Enum Singleton

In Java, using an enum is a simple, effective way to create a singleton. Enum singletons are thread-safe, provide serialization out of the box, and prevent additional instances from being created, even during deserialization.

public enum Logger {
    INSTANCE; // The single instance of the singleton

    // Private constructor - automatically called once when the INSTANCE is created
    Logger() {
        System.out.println("Logger instance created.");
    }

    // Method to log messages
    public void log(String message) {
        System.out.println("Log: " + message);
    }

    // Method to log error messages
    public void error(String message) {
        System.out.println("Error: " + message);
    }
}
public class Main {
    public static void main(String[] args) {
        // Access the singleton instance
        Logger logger = Logger.INSTANCE;

        // Use the logger to log messages
        logger.log("Application started");
        logger.error("An error occurred");

        // Access the singleton instance again
        Logger anotherLogger = Logger.INSTANCE;

        // Demonstrate that both references point to the same instance
        System.out.println("Are both instances the same? " + (logger == anotherLogger));
    }
}


Logger instance created.
Log: Application started
Error: An error occurred
Are both instances the same? true

Summary

Each of these methods has its own advantages:

  • Eager Initialization: Simple and thread-safe but may create instances unnecessarily.
  • Lazy Initialization: Saves resources by creating an instance only when needed, but requires synchronization.
  • Enum Singleton: The most effective, thread-safe approach that handles serialization and reflection automatically.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *