Java的对象不仅可以new关键字产生,也可以利用clone()方法产生,或者利用反射和反序列化产生。用DCL或静态内部类实现单例模式都是利用private修饰构造函数来解决new关键字产生多个对象的问题的,但单例模式仍然可以被clone()方法、反射和反序列化破坏。
如下代码所示,让单例类实现Cloneable接口,同时重写clone()方法:
// Cloneable接口的作用是让clone()生效
public class Singleton implements Cloneable{
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
@Override
public Singleton clone(){
try{
return (Singleton) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
比较原始对象与克隆对象
Singleton singleton = Singleton.getInstance();
Singleton singletonClone = singleton.clone();
System.out.println("比较原型对象与克隆对象:"+(singleton == singletonClone));
运行结果:
比较原型对象与克隆对象:false |
从结果上看,确实创建了两个不同的对象。为了防止clone()方法破坏单例模式的解决思路非常简单,只要单例类不实现Cloneable接口即可,或者用如下方式重写clone()方法:
@Override
public Singleton clone(){
return instance;
}