【Java】序列化与单例

来源:互联网 发布:手机淘宝白夜追凶视频 编辑:程序博客网 时间:2024/06/16 17:55

之前明白了 线程安全且延迟加载的单例如何写,有两种,双重检验和静态内部类。然后为了防止反射破坏单例,在私有构造方法里面加入了一个同步变量的判断,确保构造方法只调用一次。但是仍然无法阻止序列化破坏单例,例子:

package gggg;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;public class S implements Serializable {private S(){System.out.println("con");}static class SS{private static S s = new S();}public static S instance(){return SS.s;}public static void main(String[] args) {try {S s1 = S.instance();FileOutputStream out = new FileOutputStream("a");ObjectOutputStream outt = new ObjectOutputStream(out);outt.writeObject(s1);FileInputStream in = new FileInputStream("a");ObjectInputStream inn = new ObjectInputStream(in);S s2 = (S) inn.readObject();System.out.print(s1 == s2);} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
可以看到这里是false,说明有两个实例。

在readObj底层实现上,是通过反射调用私有构造方法来返回实例的,但是在这段代码后面,还会检测该类是否有一个readResolve()方法,如果有,就返回这个方法返回值。这个方法必然是为了解决序列化破坏单例的,我们可以添加这个方法,让其返回单例。

所以在单例类中添加如下方法:

public Object readResolve(){return instance();}

最后再执行,就是true了,说明返回了同一个对象。



原创粉丝点击