[英]Serialization with singleton design pattern
我在使用单例模式对类进行序列化时遇到问题。 首先让我介绍一下代码:
import java.io.ObjectStreamException;
import java.io.Serializable;
import org.ejml.simple.SimpleMatrix;
public class Operation implements Serializable {
private static final long serialVersionUID = 1L;
private final static int CONSTANT = 10;
private SimpleMatrix data;
private Long timestamp;
private static Operation instance = new Operation ();
private Operation () {
data = new SimpleMatrix(1, CONSTANT);
}
protected static Operation getInstance() {
return instance;
}
//Hook for not breaking the singleton pattern while deserializing.
private Object readResolve() throws ObjectStreamException {
return instance;
}
protected void setData(SimpleMatrix matrix) {
this.data = matrix;
}
protected SimpleMatrix getData() {
return data;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
}
我有三个问题,希望有人能帮助我:
据我所知,静态字段没有序列化。 因此,如果我反序列化,我的最终静态字段CONSTANT是否设置为10? 如果没有,我该怎么做? 这个非常重要。
如您所见,在构造函数中创建了一个新矩阵。 如果我反序列化,此构造函数会覆盖我的data
吗? 对于反序列化,我需要序列化版本的data
,而不是新的矩阵。 构造函数我只需要在序列化之前第一次实例化该对象。
在序列化之前,我将字段timestamp
设置为序列化的时间。 反序列化后,我想将此字段与某些文件的时间戳进行比较(以查看自序列化以来文件是否已更改)。 我应该为文件的序列化时间和上次修改时间使用哪种时间戳,以便可以轻松比较?
静态常量与该类相关联,因此实例的序列化和反序列化完全不会对其产生影响。
为了使反序列化起作用,您需要将单例的数据设置为反序列化的实例数据:
private Object readResolve() throws ObjectStreamException { instance.setData(getData()); return instance; }
时间戳记可以保持为Long,这很好。 使用System.currentTimeMillis(),您将能够与File对象的lastModified()日期进行比较。 只需在序列化时设置字段即可:
private void writeObject(java.io.ObjectOutputStream out) throws IOException{ timestamp=System.currentTimeMillis(); out.defaultWriteObject(); }
为了确保我所说的,我做了一个测试,使用字符串而不是代码中的矩阵:
public static void main(String[] args) throws Exception {
Operation op=getInstance();
op.setData("test1");
byte[] ds=serialize();
System.out.println(new Date(getInstance().timestamp));
op.setData("test2");
deserialize(ds);
System.out.println(getInstance().getData());
}
这给了我当前日期和test1
,因为反序列化实例已覆盖当前实例。 serialize
和deserialize
serialize
只需在实例和字节之间进行转换即可。
我建议您采用Enum Singleton方法来实现Singleton,因为处理Serialization是免费的。 在你的情况下
public enum Operation {
INSTANCE;
// No need to handle Serialization
}
用有效Java引用Joshua Bloch: “ 单元素枚举类型是实现单例的最佳方法。 ”
这种方法有很多好处,您可以在这里找到
而且对于实例控件,更喜欢枚举类型来读取
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.