1

It is a good practices to define INSTANCE in an Enum, for the benefit of serialization for free (Effective Java Edition 2, Item 3). If anyone could explain a bit more what it means, it will be great.

What is the best approach for using an Enum as a singleton in Java?

thanks in advance, Lin

Community
  • 1
  • 1
Lin Ma
  • 9,739
  • 32
  • 105
  • 175
  • I can't explain something I can't read. I also don't see how the link relates to the question you are asking. Please explain the connection. – Stephen C Apr 12 '15 at 03:17
  • 1
    Impossible to answer definitively without the text in question, but I'm going to guess that the author is suggesting that the best approach to *create a Singleton* is with an `enum`... However, dealing with `Serialization` can be difficult with a *`Singleton`* that isn't implemented as an `enum` (and you can try it yourself if you like). So the author's assertion does not seem without merit. – Elliott Frisch Apr 12 '15 at 03:20
  • It's generally good practice to do whatever it says in that book. – Paul Boddington Apr 12 '15 at 03:21

1 Answers1

5

Here's a demonstration:

import java.io.*;

class ClassSingleton implements Serializable {
    public static final ClassSingleton INSTANCE = new ClassSingleton();

    private ClassSingleton() {}
}

enum EnumSingleton {
    INSTANCE;
}

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        byte[] data;
        try (ByteArrayOutputStream output = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(output)) {
            oos.writeObject(ClassSingleton.INSTANCE);
            oos.writeObject(EnumSingleton.INSTANCE);
            data = output.toByteArray();
        }

        try (ByteArrayInputStream input = new ByteArrayInputStream(data);
             ObjectInputStream ois = new ObjectInputStream(input)) {
            ClassSingleton first = (ClassSingleton) ois.readObject();
            EnumSingleton second = (EnumSingleton) ois.readObject();

            System.out.println(first == ClassSingleton.INSTANCE);
            System.out.println(second == EnumSingleton.INSTANCE);
        }
    }
}

Here we have both a "simple" class-based singleton, and the enum-based version.

We write out both instances to an ObjectOutputStream, then read them back again. The output is false then true, showing that with the class-based singleton, we've ended up with two instances of ClassSingleton... our "normal" one, and the one created by deserialization. We only have one instance of EnumSingleton however, because enums have serialization/deserialization code to preserve their "fixed set of values" nature. You can write this code for the class-based singleton too, but it's easier not to have to.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks @Jon, what is the benefit of one instance (in the case of Enum)? – Lin Ma Apr 13 '15 at 07:04
  • @LinMa: Well it's not a singleton if there are multiple instances :) You end up with reference equality and lower memory use. – Jon Skeet Apr 13 '15 at 08:05
  • it makes senses, and if a program runs to complete (JVM shutdown) and then restarts (a new JVM instance), how single instance helps in this scenario (start a new JVM)? – Lin Ma Apr 13 '15 at 21:11
  • @LinMa: No, it's a single instance within a JVM, whether that instance has been obtained via deserialization or just using `EnumSingleton.INSTANCE`. – Jon Skeet Apr 14 '15 at 06:17
  • want to confirm with you INSTANCE in ENUM only helps in single SVM to control only one instance is created? – Lin Ma Apr 14 '15 at 23:14
  • @LinMa: Assuming you meant JVM, then yes - that's basically the definition of a singleton. – Jon Skeet Apr 15 '15 at 06:03