- First take a look at the singleton class implemented by enumeration
- Ordinary class
public class Controller { public Controller() { } public void func(){ System.out.println("1"); }}Copy the code
- 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
- 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
- In the source directory, execute
javac ./*.java
Compile all files under the package - Use Java to decompile with javap
javap .\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.class
A 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
public final class ControllerHolder extends Enum
This line saysAn enumeration is a normal class that extends from the Enum class.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- 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