有人在iteye上提出了单例类的问题,下面是一个精彩的回答。
写一个单例应该需要考虑一个重要问题,对象是怎么创建的:
1、通过构造函数创建
2、通过反射创建
3、通过反序列化创建
4、通过clone创建
提供的解决方案如下:
1、禁止外部调用构造函数设置 private
2、禁止反射设置构造函数创建accessable,调用构造函数,可以再构造函数内判断是否已经创建过对象
3、禁止反序列化创建对象,需要重写readResolve方法
4、禁止clone,其实也不算禁止吧,重新clone,返回你的引用就OK
你看看你的单例有没有处理这几种情况,关于synchronized,个人还是觉得需要使用,考虑到线程安全问题
单例类的序列化
一个单例类要想序列化,仅让其实现serializable 是不够的,还需要写
private Object readResolve() throws ObjectStreamException {
return instance;
}//这个方法可以在反序列化之后内存中不会有该类的多个实例
如下,进行序列化/反序列化
public static void main(String[] args) throws Exception {
// 序列化
ObjectOutputStream objectOutputStream = new ObjectOutputStream(
new FileOutputStream("c:\\Singleton.clazz"));
Singleton singleton = Singleton.uniqueInstance;
objectOutputStream.writeObject(singleton);
objectOutputStream.close();
// 反序列化
ObjectInputStream objectInputStream = new ObjectInputStream(
new FileInputStream("c:\\Singleton.clazz"));
Singleton singleton2 = (Singleton) objectInputStream.readObject();
objectInputStream.close();
// 比较是否原来的实例
System.out.println(singleton == singleton2);
}//如果不加readResolved方法,两个结果不相等,加上,则相等。