CodeGym /Courses /Module 1. Java Syntax /Singleton as enum

Singleton as enum

Module 1. Java Syntax
Level 20 , Lesson 2
Available

You recently delved into the singleton design pattern, how to implement it in Java, and what it is for. But what if I tell you that Java comes with its own singleton out of the box? Intrigued? Then let's dive in.

You probably already know about the Enum class. It has a special feature that you should be aware of. Specifically, Enum implements the singleton design pattern. This option is almost the same as the singleton approach involving a public field.

Singleton as enum:


public enum Device {   
    PRINTER	
} 
    

Singleton as a public variable:


public class Printer {   
    public static final Printer PRINTER = new Printer();   
    private Printer() {
    }
//…
}
    

The enum approach is more compact than the public-field approach, since we don't need to write our own implementation. Most importantly, enums have no problems with serialization.

Serialization of enums works differently than it does for ordinary objects: only the value of the enum name is serialized. During deserialization, the method is used with the deserialized name to get an instance. Additionally, enum can protect you against reflection attacks.

You'll learn more about reflection in the lessons in the second module, where we will explore the Reflection API.

Java prohibits instantiating enums —a limitation baked into the implementation of the Constructor class's newInstance method, which is often called when creating objects through reflection.

Excerpt of code from Constructor.newInstance. Used to create an enum:


if ((clazz.getModifiers() & Modifier.ENUM) != 0)
    throw new IllegalArgumentException("Cannot reflectively create enum objects");
    

The disadvantages of using an enum to create a singleton include:

  • Lack of lazy initialization, since the object is created immediately and initialization cannot be delayed.

  • Other classes cannot be extended. That is, in cases where you need to inherit another class, it won't work to use an enum as a singleton. In such cases, we need to turn to the other implementation options already familiar to us: a static method or a public variable.

  • When using enum as a singleton, you can only use one enum field.


public enum Device extends Electricity { 
    PRINTER 
}
    

This code will give us a compilation error:

No extends clause allowed for enum

But if we need to implement an interface, there is no problem, since enum can implement interfaces:


public enum Device implements Electricity { 
    PRINTER 
}
    

If you don't need to use inheritance, it's best to implement the singleton pattern via enum. We aren't alone in recommending this — Joshua Bloch himself does as well.

This implementation approach gives you convenience, compactness, serialization out of the box, protection from reflection attacks, and uniqueness — everything that a good singleton needs!

Comments (5)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Ranganathan Kasiganesan Level 94, Chennai, India Expert
21 December 2023
I solved this problem by just creating a constructor for enum. But I did this after reading the opinions of Parsa and Dmytro Sir. So, I sincerely thank both of you for your clarifications.
Parsa Level 83, Bangalore, India Expert
19 December 2023
I achieved the task's objective by creating a static block in the enum instead of using a constructor. I wonder what the point of the task was.
Dmytro Level 108, CLE,OH, USA Expert
20 December 2023
no need to use a static block at all. You can do it much more simply. Logically, your approach is not correct since static block responses for Class-side operations when here it says you just need to print a message related to the object(creating an obj).
Parsa Level 83, Bangalore, India Expert
19 December 2023
Joshua Bloch link is broken.
Abhishek Tripathi Level 72, Rewa, India Expert
28 July 2023
Cool topic! I loved the use of Enum as Singleton.