Share the joy
Singleton with public final field
Problem of this is that this can create another instance by reflection. The fix is that in private method, add a INSTANCE check.
public class SingletonWithPublicFinalField { public static final SingletonWithPublicFinalField INSTANCE = new SingletonWithPublicFinalField(); private SingletonWithPublicFinalField() { // if (INSTANCE != null) { // throw new RuntimeException("Singleton instance already existed"); // } } public static void main(String[] args) throws Exception{ SingletonWithPublicFinalField instance1 = SingletonWithPublicFinalField.INSTANCE; System.out.println(instance1); Constructor.setAccessible(SingletonWithPublicFinalField.class.getConstructors(), true); Object instance2 = Class.forName(SingletonWithPublicFinalField.class.getName()).newInstance(); System.out.println(instance2); } }
Singleton with public static factory method. Good of it is that it is very like a class. It is easy to convert it into a normal non-singleton class. Just rewrite getInstance() method.
public class SingletonWithPublicStaticFactoryMethod { public static final SingletonWithPublicStaticFactoryMethod INSTANCE = new SingletonWithPublicStaticFactoryMethod(); private SingletonWithPublicStaticFactoryMethod() {} public static SingletonWithPublicStaticFactoryMethod getInstance() { return INSTANCE; } public static void main(String[] args) throws Exception{ SingletonWithPublicStaticFactoryMethod instance = SingletonWithPublicStaticFactoryMethod.getInstance(); System.out.println(instance); } }
Singleton serializable issue. When deserializing, it creates a different instance. The fix is to override readResolve() method and return the INSTANCE.
public class SingletonWithSerializable implements Serializable { public static final SingletonWithSerializable INSTANCE = new SingletonWithSerializable(); private SingletonWithSerializable() {} public static SingletonWithSerializable getInstance() { return INSTANCE; } // When deserializing, it returns a different instance. The fix is to add below // private Object readRsolve() { // return INSTANCE; // } public static void main(String[] args) throws Exception{ SingletonWithSerializable instance = SingletonWithSerializable.getInstance(); System.out.println(instance); try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file1.ser"))) { out.writeObject(instance); } try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("file1.ser"))) { SingletonWithSerializable readObject = (SingletonWithSerializable) in.readObject(); System.out.println(readObject); } } }
The best option is to use enum singleton. It avoids reflection hacking or serializing issue very easily.
public enum SingletonWithEnum { INSTANCE; public void doSomeMethod() { System.out.println("some method"); } public static void main(String[] args) throws Exception { SingletonWithEnum singletonWithEnum = SingletonWithEnum.INSTANCE; SingletonWithEnum instance = SingletonWithEnum.INSTANCE; System.out.println(instance); try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file1.ser"))) { out.writeObject(instance); } try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("file1.ser"))) { SingletonWithEnum readObject = (SingletonWithEnum) in.readObject(); System.out.println(readObject); } instance.doSomeMethod(); } }