readResolve方法和单例模式

一个单例对象创建好后,有时候需要将对象序列化然后写进磁盘,下次使用时再从磁盘中读取对象并进行反序列化,将其转换为内存对象,反序列化后的对象会重新分配内存,即重新创建。如果序列化的目标为单列对象,就会破坏单例模式。

public class SerialSingleton implements Serializable {

	public final static SerialSingleton INSTANCE = new SerialSingleton();
	
	private SerialSingleton() {}
	
	public static SerialSingleton getInstance() { return INSTANCE; }
	
}

/** 测试类*/
public class SerialSingletonTest {

	public static void main(String[] args) {
		SerialSingleton s1 = null;
		SerialSingleton s2 = SerialSingleton.getInstance();
		
		FileOutputStream fos = null;
		
		try {
			fos = new FileOutputStream("SerialSingleton.obj");
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			
			oos.writeObject(s2);
			oos.flush();
			oos.close();
			
			FileInputStream fis = new FileInputStream("SerialSingleton.obj");
			ObjectInputStream ois = new ObjectInputStream(fis);
			s1 = (SerialSingleton) ois.readObject();
			ois.close();
			
			System.out.println(s1);
			System.out.println(s2);
			System.out.println(s1 == s2);
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}

运行结果:

com.singleton.seriable.SerialSingleton@6e3c1e69
com.singleton.seriable.SerialSingleton@7b3300e5
false
 

显然,序列化会破坏单例.....emm那要怎么办,这时候有一个叫readResolve()的方法出现了。就很神奇,把他放在SerialSingleton类中,再次运行

public class SerialSingleton implements Serializable {

	public final static SerialSingleton INSTANCE = new SerialSingleton();
	
	private SerialSingleton() {}
	
	public static SerialSingleton getInstance() { return INSTANCE; }
	
	private Object readResolve() { return INSTANCE; }
}

com.singleton.seriable.SerialSingleton@33909752
com.singleton.seriable.SerialSingleton@33909752
true

喜极而泣!!

冷静一下,emm为什么会这样呢??去看源码去看源码,看下ObjectInputStream的readObject()方法,因为是通过readObject方法拿到的s1呀 ~ ~

通过分析源码知道了在readObject方法中,会通过反射去找无参的readResolve() 方法,并调用。所以通过增加readResolve()方法返回实例可以解决单例模式被破坏的问题。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值