序列化对象的singleton

  由于对象反序列化对象,总会生出一个新的实例,这使得原本的singleton对象,一旦实现了Serializable接口,就不能正常工作了,看代码:

 

public class Singleton implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -5902363018159528162L;

	private int count = 0;
	
	private static Singleton instance = new Singleton();
	static {
		System.out.println("static");
		instance = new Singleton();
	}
	private Singleton(){
	}
	
	public static Singleton getInstance(){
		return instance;
	}
	
	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}
}

 

 

测试代码:

 

@Test
	public void testSingletonWithSerializable() {
		storeSingleton();
		Singleton singleton = null;
	    singleton = restore();
	    singleton.setCount(10);
	    Singleton singleton1 = restore();
	    Assert.assertEquals(10, singleton1.getCount());
	}

	private Singleton restore() {
		Singleton singleton=null;
		try {
		    FileInputStream fis = new FileInputStream("d:\\singleton.txt");
		    ObjectInputStream ois = new ObjectInputStream(fis);
		    
		    singleton = (Singleton)ois.readObject();
		    
		} catch (Exception e) {
		    // TODO: handle exception
		    e.printStackTrace();
		}
		return singleton;
	}

	private void storeSingleton() {
		Singleton singleton = Singleton.getInstance();
	        try {
	            FileOutputStream fos = new FileOutputStream("d:\\singleton.txt");
	            ObjectOutputStream oos = new ObjectOutputStream(fos);
	            oos.writeObject(singleton);
	            oos.flush();
	            oos.close();
	        } catch (Exception e) {
	            // TODO: handle exception
	            e.printStackTrace();
	        }
	}

 

 运行后结果:

 

 写道

junit.framework.AssertionFailedError: expected:<10> but was:<0>
at junit.framework.Assert.fail(Assert.java:47)
at junit.framework.Assert.failNotEquals(Assert.java:283)
at junit.framework.Assert.assertEquals(Assert.java:64)
at junit.framework.Assert.assertEquals(Assert.java:195)
at junit.framework.Assert.assertEquals(Assert.java:201)
at ully.designpattern.singleton.SingletonTest.testSingletonWithSerializable(SingletonTest.java:32)

 

 显然,第二次读取的singleton对象是新的。

 

 

如此,如何解决此问题呢,答案是需要在Singleton类中添加一个回调方法:

 

 

private Object readResolve(){
		return instance;
	}

 这其实就相当于做了一个hack,代码在执行ObjectInputStream的readObject()方法时,会先去检查该序列化类是否有readResolve方法,如果有会将object替换成ReadResolve方法返回的对象。

 

 

 

/**
     * Invokes the readResolve method of the represented serializable class and
     * returns the result.  Throws UnsupportedOperationException if this class
     * descriptor is not associated with a class, or if the class is
     * non-serializable or does not define readResolve.
     */
    Object invokeReadResolve(Object obj)
	throws IOException, UnsupportedOperationException
    {
	if (readResolveMethod != null) {
	    try {
		return readResolveMethod.invoke(obj, (Object[]) null);
	    } catch (InvocationTargetException ex) {
		Throwable th = ex.getTargetException();
		if (th instanceof ObjectStreamException) {
		    throw (ObjectStreamException) th;
		} else {
		    throwMiscException(th);
		    throw new InternalError();	// never reached
		}
	    } catch (IllegalAccessException ex) {
		// should not occur, as access checks have been suppressed
		throw new InternalError();
	    }
	} else {
	    throw new UnsupportedOperationException();
	}
    }

 

 

如此,添加了ReadResolve方法,即可保证每次反序列化的对象均是单例的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>