众所周知,一般使用java实现单例模式有两种方法,分别为急切式(饥饿式)和双重加锁式,急切式就是在声明时即创建,这样在类加载时就已经创建好了,即时我们可能并不不需要它,它的生命周期是永久的,造成内存泄漏的可能!第二种方式是lazy的,只有在使用时创建,实现了延迟加载。代码为
1.急切式
class Singleton { private final static Singleton instance = new Singleton(); private Singleton(){ } public static Singleton getInstance() { return instance; } }
2. 双重加锁式
class Singleton { private volatile static Singleton instance = null; private Singleton(){ } public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
还有一种方法是使用内部类的方法,这主要为克服方法1中的问题,既能实现延迟加载,又能保证线程安全,而且性能不错。代码为:
class Singleton { private Singleton() { } private static class Holder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return Holder.INSTANCE; } }
以上方法都是通过使用private构造方法来阻止外部直接创建对象,但如果使用反射机制,则不能保证实例的唯一性了!!!
public class SingletonDemo { //@SuppressWarnings("unchecked") //public static <T> T newInstance(Class<?> cl) { // T t = null; // try { // t = (T)cl.newInstance(); /* 只能调用public构造方法 */ // } catch(Exception e) { // e.printStackTrace(); // } // return t; //} @SuppressWarnings("unchecked") public static <T> T newInstance(Class<?> cl) { T t = null; try { Constructor<?> constructor = cl.getDeclaredConstructor(); constructor.setAccessible(true); t = (T)constructor.newInstance(); } catch(Exception e) { e.printStackTrace(); } return t; } @SuppressWarnings("unchecked") public static <T> T newInstance(Class<?> cl, Class<?>...args) { T t = null; try { Constructor<?> constructor = cl.getDeclaredConstructor(args); constructor.setAccessible(true); t = (T)constructor.newInstance("name", 1); } catch(Exception e) { e.printStackTrace(); } return t; } public static void main(String[] args) { Singleton instance = Single.INSTANCE; Singleton s1 = newInstance(Singleton.class, String.class, int.class); Singleton s2 = newInstance(Singleton.class, String.class, int.class); //Tmp t1 = newInstance(Tmp.class); //Tmp t2 = newInstance(Tmp.class); //System.out.println(s1 == s2); //System.out.println(t1 == t2); } }
Joshua Bloch (Effect java 作者)提出一种新的方法实现单例模式,就是使用Enum(其实也是类,一种特殊的类,构造方法必须是private ,final的)!如下:
enum Singleton { INSTANCE; public void sayHi() { System.out.println("Hi"); } }
这样当试图通过反射机制创建对象时,会抛出异常!
2018年11月01日 21:41
good tutorial
2021年4月29日 14:48
Great knowledge, do anyone mind merely reference back to it 123movies
2023年1月01日 01:10
The singleton mode cannot be implemented using private constructor in java because it would not be able to instantiate the class. The private constructor cbd benefits would be unable to access the class, which means that it would not be able to create an instance of the class. Consequently, the singleton mode would not be able to function properly.
2024年6月21日 05:51
It's late finding this act. At least, it's a thing to be familiar with that there are such events exist. I agree with your Blog and I will be back to inspect it more in the future so please keep up your act. turkey embassy in japan