package singleton;
/**
*@author Danbro
*@version 创建时间:2019年6月26日下午3:42:51
*@funcition 懒汉式单例模式
**/
public class SingTonDemo06 {
private static SingTonDemo06 instance;
private SingTonDemo06() {
}
public static synchronized SingTonDemo06 getInstance() {
if (instance == null) {
instance = new SingTonDemo06();
}
return instance;
}
}
运行
package singleton;
import java.lang.reflect.Constructor;
/**
*@author Danbro
*@version 创建时间:2019年6月26日下午4:33:30
*@funcition
**/
public class Client02 {
public static void main(String[] args) throws Exception {
SingTonDemo06 s1 = SingTonDemo06.getInstance();
SingTonDemo06 s2 = SingTonDemo06.getInstance();
System.out.println(s1);
System.out.println(s2);
//运用反射
Class<SingTonDemo06> claz = (Class<SingTonDemo06>) Class.forName("singleton.SingTonDemo06");
//通过反射获得原本私有的无参构造器
Constructor<SingTonDemo06> c = claz.getDeclaredConstructor(null);
//关闭安全检查
c.setAccessible(true);
//通过构造器实例化对象
SingTonDemo06 s3 = c.newInstance();
SingTonDemo06 s4 = c.newInstance();
System.out.println(s3);
System.out.println(s4);
}
}
singleton.SingTonDemo06@15db9742
singleton.SingTonDemo06@15db9742
singleton.SingTonDemo06@6d06d69c
singleton.SingTonDemo06@7852e922
会发现 通过反射可以破解单例模式
这样修改SingTonDemo06代码
package singleton;
/**
*@author Danbro
*@version 创建时间:2019年6月26日下午3:42:51
*@funcition 懒汉式单例模式
**/
public class SingTonDemo06 {
private static SingTonDemo06 instance;
private SingTonDemo06() {
//如果对象不为空 则抛出异常
if (instance != null) {
throw new RuntimeException();
}
}
public static synchronized SingTonDemo06 getInstance() {
if (instance == null) {
instance = new SingTonDemo06();
}
return instance;
}
}
通过反序列化的方式构造多个对象
package singleton;
/**
*@author Danbro
*@version 创建时间:2019年6月26日下午3:42:51
*@funcition 懒汉式单例模式
**/
import java.io.Serializable;
public class SingTonDemo07 implements Serializable{
private static SingTonDemo07 instance;
private SingTonDemo07() {
//如果对象不为空 则抛出异常
if (instance != null) {
throw new RuntimeException();
}
}
public static synchronized SingTonDemo07 getInstance() {
if (instance == null) {
instance = new SingTonDemo07();
}
return instance;
}
}
package singleton;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
/**
*@author Danbro
*@version 创建时间:2019年6月26日下午4:33:30
*@funcition 通过反序列化的方式构造多个对象
**/
public class Client03 {
public static void main(String[] args) throws Exception {
SingTonDemo07 s1 = SingTonDemo07.getInstance();
SingTonDemo07 s2 = SingTonDemo07.getInstance();
System.out.println(s1);
System.out.println(s2);
//序列化 把对象存到硬盘上
FileOutputStream fos = new FileOutputStream("D:/a.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s2);
fos.close();
oos.close();
//反序列化 从硬盘上读取对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/a.txt"));
SingTonDemo07 s3 = (SingTonDemo07) ois.readObject();
System.out.println(s3);
}
}
singleton.SingTonDemo07@15db9742
singleton.SingTonDemo07@15db9742
singleton.SingTonDemo07@776ec8df
会发现 序列化前的对象和序列化后的对象不是同一个对象,破解了单例
解决办法
定义一个readResolve方法
在反序列化时会调用此方法而不需要再反序列化另一个对象
package singleton;
/**
*@author Danbro
*@version 创建时间:2019年6月26日下午3:42:51
*@funcition 懒汉式单例模式
**/
import java.io.Serializable;
public class SingTonDemo07 implements Serializable{
private static SingTonDemo07 instance;
private SingTonDemo07() {
//如果对象不为空 则抛出异常
if (instance != null) {
throw new RuntimeException();
}
}
public static synchronized SingTonDemo07 getInstance() {
if (instance == null) {
instance = new SingTonDemo07();
}
return instance;
}
//在反序列化时会调用此方法而不需要再反序列化另一个对象
private Object readResolve(){
return instance;
}
}
singleton.SingTonDemo07@15db9742
singleton.SingTonDemo07@15db9742
singleton.SingTonDemo07@15db9742