利用类加载机制的饿汉单例模式.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package singleton;
public class Singleton { public static Singleton instance() { return Inner.s; }
private static class Inner { private static Singleton s = new Singleton(); }
private Singleton() { } }
|
最近刚发现有另外一种单例模式写法,堪称史上最简洁的;果真被惊艳到了,我发现自己对单例模式的认识很肤浅。就像上一个例子,它明明是懒汉单例模式的实现,但是内部类却是饿汉模式,为什么它可以保证在多线程情况下实例唯一,我还是搞不清楚。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| package common;
public class SingletonA { private SingletonA() { System.out.println("instance A: " + this.hashCode()); }
private static class SingletonHolder { private static final SingletonA s = new SingletonA(); }
public static SingletonA getInstance() { return SingletonHolder.s; }
public void fun() { System.out.println("hello"); } }
package common;
public enum SingletonB { INSTANCE;
void fun() { System.out.println("singletonB: " + this.hashCode()); } }
package common;
import java.lang.reflect.Constructor; import java.lang.reflect.Method;
public class UseCase { public static void main(String[] args) { try { SingletonB.INSTANCE.fun();
Class clazz = SingletonB.class; Object[] cs = clazz.getEnumConstants(); Method m = clazz.getDeclaredMethod("fun"); m.invoke(cs[0]); Object[] cs2 = clazz.getEnumConstants(); Method m2 = clazz.getDeclaredMethod("fun"); m2.invoke(cs2[0]);
SingletonA singletonA = SingletonA.getInstance(); singletonA.fun();
Class clazz2 = SingletonA.class; Constructor constructor = clazz2.getDeclaredConstructor(); constructor.setAccessible(true); SingletonA singletonA1 = (SingletonA) constructor.newInstance(); singletonA1.fun(); } catch (Exception ex) { ex.printStackTrace(); } } }
|
通过UseCase可以发现,SingletonA是可以通过反射获取多个实例的,而enum单例却不能通过反射产生多个实例。