本文意在和谐讨论,高手勿喷~
单例模式容易忽略的几点:
1.第三种单例实现(除了懒汉和饿汉)
2.构造函数私有化(单例的核心)
3.即便构造函数私有化了也不能保证只有一个实例
下面我们来详细阐述:
1.第三种单例实现(除了懒汉和饿汉)
- 饿汉模式无论你是否会用到,上来都会创建实例。
- 懒汉模式只有在用到的时候才会创建,但是为了不产生多线程的问题,需要加synchronized来保证线程安全,但是每次使用的时候都需要带着保证线程安全的操作,无形增加了系统的开销.
于是使用第三种方式(内部类方式)来同时解决懒汉和恶汉的弊端
package com.cxy.singleton;
/** 内部类方式
* @author cxy
*/
public class InnerClassSingleton {
//私有构造子 (保证整个系统只有一个实例)
private InnerClassSingleton(){
System.out.println("InnerClassSingleton 实例化");
}
//内部类
private static class SingletonHolder {
private static InnerClassSingleton instance = new InnerClassSingleton();
}
public static InnerClassSingleton getInstance()
{
return SingletonHolder.instance;
}
}
2.构造函数私有化(单例的核心)
为了保证整个系统只有一份实例,我们使用构造函数私有化的方式来保证,系统不会new出第二个实例。
3.即便构造函数私有化了也不能保证只有一个实例
其实即便构造函数私有化了,我们还是可以通过反射的方法来new出第二份实例的。
package com.cxy.singleton;
import java.lang.reflect.Constructor;
import org.junit.Test;
public class DestroyTest {
@Test
public void test() throws Exception
{
HungrySingleton obj1=HungrySingleton.getInstance();
HungrySingleton obj2=HungrySingleton.getInstance();
System.out.println("obj1和obj2是否相等:"+(obj1==obj2));
System.out.println("=====================");
//通过构造方法赋权限 让私有构造函数 可以实例化
HungrySingleton obj3=null;
HungrySingleton obj4=null;
Constructor[] cons = Class.forName("com.cxy.singleton.HungrySingleton").getDeclaredConstructors();
if(cons.length==1)
{
cons[0].setAccessible(true);
obj3=(HungrySingleton)cons[0].newInstance();
obj4=(HungrySingleton)cons[0].newInstance();
}
System.out.println("obj3和obj4是否相等:"+(obj3==obj4));
}
}
如果你还知道有什么其他的关于单例"不为人知"的信息,欢迎指教讨论~
转载请保留原文地址!