我们为什么要实现Serializable接口,然后在同一个类中添加readResolve

时间:2015-12-30 12:03:41

标签: java serialization singleton

我已经阅读过关于Singleton实现的更好方法。

有人提到,

  • 如果singleton类正在实现Serializable接口,那么我们必须定义readResolve方法。

但我不明白一件事。如果readResolve方法将替换序列化值,那么为什么我们要进行序列化过程?相反,我们不需要实现可序列化的接口知道吗?

例如,我有以下Singleton类,

package singleton;

import java.io.Serializable;

public class ClassicSingleton implements Serializable {

private static final long serialVersionUID = 1L;

private static ClassicSingleton classicSingleton = new ClassicSingleton();

private int num;

private ClassicSingleton() {

}

public int getNum() {
    return num;
}

public void setNum(int num) {
    this.num = num;
}

public static ClassicSingleton getInstance() {
    return classicSingleton;
}

protected Object readResolve() {
    ClassicSingleton cs = getInstance();
    cs.setNum(23);
    return cs;
}

}

这就是我正在进行序列化的地方,

package singleton;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SingletonExample {
public static <T> void main(String args[]) throws FileNotFoundException,
        IOException, ClassNotFoundException {

    ClassicSingleton classicSingleton = ClassicSingleton.getInstance();
    classicSingleton.setNum(5);
    serialize(classicSingleton);
    }

public static <T> void serialize(T t) throws FileNotFoundException,
        IOException {

    ObjectOutputStream oop = new ObjectOutputStream(new FileOutputStream(
            "file1.txt"));
    oop.writeObject(t);
    oop.close();

}

}

DeSerialization code

package singleton;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;

public class SerializeInAnotherFIle {

public static <T> void main(String[] args) throws FileNotFoundException,
        ClassNotFoundException, IOException {

    T object = deSerialize();

    ClassicSingleton classicSingleton= (ClassicSingleton) object;
    ClassicSingleton classicSingleton2 = deSerialize();
    System.out.println("Is serialized and deserialized are same? :"+(classicSingleton == classicSingleton2));

    System.out.println("Classic Singleton :"
            + classicSingleton.getNum());

}

public static <T> T deSerialize() throws FileNotFoundException,
        IOException, ClassNotFoundException {

    ObjectInputStream oip = new ObjectInputStream(new FileInputStream(
            "file1.txt"));
    T object = (T) oip.readObject();
    oip.close();
    return object;

}}

因为,我正在定义我的readResolve方法,我的输出总是23.序列化值不会到来。所以我怀疑为什么序列化和readResolve在一起,因为两者正在相反。

2 个答案:

答案 0 :(得分:1)

我找到了这个问题的答案 http://codepumpkin.com/serializable-singleton-design-pattern/

以下是此链接的摘要:

为什么我们需要使Singleton类可序列化?

嗯,根本不需要。没有有用的真实场景,我们需要序列化Singleton Object。单身人员在其整个生命周期中通常不会改变状态,也不包含我们可以保存/恢复的任何状态。如果确实如此,那么将其作为单身人士已经是错误的。

Java SE API包含两个Singleton实现java.lang.Runtimejava.awt.Desktop。它们都没有实现serializable。它也没有任何意义。

但是,在这种情况下,我们可能需要在实现Singleton Design Pattern时处理序列化。

如果超类已经实现了序列化界面怎么办?

如果我们的Singleton类需要继承某些类的所有属性,即ParentClass,并且该类是Serializable。例如,

class ParentClass implements Serializable{

}
public class SerializableSingleton extends ParentClass {
     // Singleton Code
}

在这种情况下,我们需要采取所有预防措施,例如使所有字段成为瞬态并提供readResolve()方法实现。

还有一种方法可以处理这种情况。覆盖writeObject()方法并从中抛出NotSerializableException。它的行为与您未实现Serializable接口的行为相同。

答案 1 :(得分:0)

原因是没有人可以通过序列化和反序列化单例来创建单例对象的另一个实例。

readResolve用于替换从流中读取的对象。你用cs.setNum(23)对它进行了硬编码;这就是它总是返回23的原因。如果您不想对数据进行操作,请按以下方式编辑代码

protected Object readResolve() {
  return this;
}

原因:readObject返回后调用readResolve。该方法返回的对象替换返回给ObjectInputStream.readObject的用户的该对象。