繁体   English   中英

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

[英]Why should we implement Serializable interface and then add readResolve in same class

我已经阅读了有关实现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();

}

}

反序列化代码

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。序列化的值不再出现。 所以我的疑问是为什么将Serialization和readResolve放在一起,因为两者的作用相反。

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

这是此链接的摘要:

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

好吧,这根本不是必需的。 在现实世界中,没有有用的场景要求我们序列化Singleton对象。 单例通常在其整个生命周期内都不会改变状态,也不包含我们可以保存/恢复的任何状态。 如果是这样,那么将其设为单身已经是错误的。

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抛出NotSerializableException 与未实现Serializable接口的行为相同。

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

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

protected Object readResolve() {
  return this;
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM