java - 为什么我们要实现 Serialized 接口(interface),然后在同一个类中添加 readResolve

标签 java serialization singleton

我读过有关单例实现的更好方法。

有人提到,

  • 如果单例类实现了 Serialized 接口(interface),那么我们必须定义 readResolve 方法。

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

例如,我有以下 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 类可序列化?

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

Java SE API 包含两个单例实现java.lang.Runtimejava.awt.Desktop。它们都没有实现可序列化。这也没有任何意义。

但是,在这种情况下,我们可能需要在实现单例设计模式时处理序列化。

如果父类(super class)实现了序列化接口(interface)怎么办?

如果我们的 Singleton 类需要继承某个类(即 ParentClass)的所有属性,并且该类是可序列化的。例如,

class ParentClass implements Serializable{

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

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

还有一种方法可以处理这种情况。重写 writeObject() 方法并从中抛出 NotSerializedException。其行为与您尚未实现 Serialized 接口(interface)相同。

关于java - 为什么我们要实现 Serialized 接口(interface),然后在同一个类中添加 readResolve,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34529213/

相关文章:

java - 如何将参数传递给 Spark 中 mapPartitions 的用户定义函数?

java - 为 bean 添加属性

java - 加密和序列化时出现 NullPointerException 异常

C# 序列化问题

c# - 多个单例实例 c#

java - 如何绑定(bind) Activity 中 NavigationView 中的 TextView

java - 如何在进度条处于 Activity 状态之前禁用控件

c# - 如何使用 json.net 反序列化派生类

ios - 静态变量如何在实例方法中工作 - 单例

android - 单例被摧毁