• First take a look at the singleton class implemented by enumeration
  1. Ordinary class
public class Controller { public Controller() { } public void func(){ System.out.println("1"); }}Copy the code
  1. I want to make it singleton (with an enumerated class holding the ordinary class that I want to implement the singleton)
public enum ControllerHolder { INSTANCE; private Controller controller; ControllerHolder() { this.controller = new Controller(); } public static Controller getInstance(){ return ControllerHolder.INSTANCE.controller; }}Copy the code
  1. Under test
public static void main(String[] args) { System.out.println(ControllerHolder.getInstance()); System.out.println(ControllerHolder.getInstance()); System.out.println(ControllerHolder.getInstance()); System.out.println(ControllerHolder.getInstance()); System.out.println(ControllerHolder.getInstance()); } output: com.iluwatar.singleton.Controller@6e8cf4c6 com.iluwatar.singleton.Controller@6e8cf4c6 com.iluwatar.singleton.Controller@6e8cf4c6 com.iluwatar.singleton.Controller@6e8cf4c6 com.iluwatar.singleton.Controller@6e8cf4c6Copy the code
  • Now it looks singleton, but is there support for multithreading? Let’s decompile it
  1. In the source directory, executejavac ./*.javaCompile all files under the package
  2. Use Java to decompile with javapjavap .\ControllerHolder.class

3. Javap decompilation is not very good, can not see the specific situation, or usejad4. Execute .\jad.exe D:\workspace_idea_try\java-design-patterns\singleton\src\main\java\com\zzk\singleton\ControllerHolder.classA controllerholder. jad file is generated in the same directory as JAD. ↓↓↓

  • Decompiled file at last
public final class ControllerHolder extends Enum { public static ControllerHolder[] values() { return (ControllerHolder[])$VALUES.clone(); } public static ControllerHolder valueOf(String s) { return (ControllerHolder)Enum.valueOf(com/zzk/singleton/ControllerHolder, s); } private ControllerHolder(String s, int i) { super(s, i); controller = new Controller(); } public static Controller getInstance() { return INSTANCE.controller; } public static final ControllerHolder INSTANCE; // Controller will be initialized with ControllerHolder initialization private controller controller; private static final ControllerHolder $VALUES[]; static { INSTANCE = new ControllerHolder("INSTANCE", 0); $VALUES = (new ControllerHolder[] { INSTANCE }); }}Copy the code
  1. public final class ControllerHolder extends EnumThis line saysAn enumeration is a normal class that extends from the Enum class.
  2. public static final ControllerHolder INSTANCE;In this line, ControllerHolder is static, andINSTANCE = new ControllerHolder("INSTANCE", 0);The JVM guarantees that running static blocks is thread-safe and only executes once, so Controller, as a ControllerHolder property, is only declared once and thread-safe
  3. The implementation of this enumeration singleton does not have the advantage of lazy loading. It does not work at first, but is initialized in static methods.
  • “Controller” and “ControllerHolder” are written separately. This method is not used because if someone directly creates a Controller, the Controller will not be a singleton. Therefore, the common way to write enumerations is to write internal enumerations as follows: ↓↓↓
Public class SingletonExample7 {private SingletonExample7() {} public static SingletonExample7 getInstance() { return Singleton.INSTANCE.getInstance(); } private enum Singleton { INSTANCE; private SingletonExample7 singleton; Singleton() {Singleton = new SingletonExample7(); Singleton = new SingletonExample7(); } public SingletonExample7 getInstance() { return singleton; }}}Copy the code