Shw*_*ani 0 java singleton serialization static deserialization
我的单例类是这样的:
public class SerializableSingleton implements Serializable {
private static SerializableSingleton instance = new SerializableSingleton();
private SerializableSingleton() {
System.out.println("Constructor is being called");
}
public static SerializableSingleton getInstance() {
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
现在网上写到,当我们反序列化这个单例对象时,它将返回一个新实例,而不是前一个实例,为了解决这个问题,请使用该readResolve()方法。
但我的问题是——这怎么可能?当静态类成员无法序列化时,如何反序列化它呢?而且全网都这样?
由于单例对象是静态的:
private static SerializableSingleton instance = new SerializableSingleton();
Run Code Online (Sandbox Code Playgroud)
实例首先是如何被序列化的?
序列化绕过了语言中的很多东西,甚至做了一些普通反射不可能完成的事情。
当对象被序列化时,它的类名和所有实例字段(不是transient)都会写入流中。
当反序列化一个对象时,奇迹就发生了。
private void readObject(ObjectInputStream)方法自定义)readResolve()调用一个方法 - 如果存在这样的方法。其结果用作反序列化对象的结果。(这不适用于records、java.lang.Class、java.lang.String、java.lang.Enum... 的实例)
在您的示例中,这意味着SerializableSingleton创建了您的新实例 - 绕过您的私有构造函数并调用java.lang.Object.<init>()- 因此您将看不到"Constructor is being called"输出。
现在您有两个“单例”实例。为了恢复原始的单例语义(该类只存在一个实例),我们用规范实例替换刚刚反序列化的实例:
private Object readResolve() {
return getInstance();
}
Run Code Online (Sandbox Code Playgroud)
tl;dr:Java 的序列化很复杂,有时与黑魔法难以区分。使用 java 的序列化为一些令人惊讶的行为打开了大门。
| 归档时间: |
|
| 查看次数: |
271 次 |
| 最近记录: |