使用单例设计模式进行序列化

时间:2016-02-25 16:13:15

标签: java serialization deserialization

我使用单例模式对类进行序列化存在问题。首先让我介绍一下代码:

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;
    }
}

我有三个问题,希望有人可以帮助我:

  1. 据我所知,静态字段没有序列化。所以如果我反序列化是我的最终静态字段CONSTANT设置为10?如果没有,我该怎么做?这非常重要。

  2. 如您所见,在构造函数中创建了一个新矩阵。如果我反序列化,我的data是否被此构造函数覆盖?对于反序列化,我想要序列化版本的data而不是新矩阵。构造函数我只需要在序列化之前第一次实例化对象。

  3. 在序列化之前,我会将字段timestamp设置为序列化时间。反序列化后,我想将此字段与某些文件的时间戳进行比较(以查看自序列化以来文件是否已更改)。我应该对文件的序列化时间和上次修改时间使用什么样的时间戳,以便我可以轻松比较?

2 个答案:

答案 0 :(得分:1)

  1. 静态常量与类相关联,因此实例的序列化和反序列化根本不会影响它。

  2. 要使反序列化生效,您需要将单例的数据设置为反序列化的实例数据:

    LinkedList
  3. 时间戳可以保持为Long,没关系。使用System.currentTimeMillis(),您将能够与File对象lastModified()日期进行比较。只需在序列化时设置字段:

    List
  4. 我已经做了一个测试,以确保我所说的,使用字符串而不是代码中的矩阵:

    private Object readResolve() throws ObjectStreamException {
        instance.setData(getData());
        return instance;
    }
    

    这为我提供了当前日期和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只需在实例和字节之间进行转换。

答案 1 :(得分:0)

我建议您采用 Enum Singleton 方法来实现单例,因为处理序列化将免费完成。在你的情况下,它将是

public enum Operation {
    INSTANCE; 
    // No need to handle Serialization 
}

引用有效Java中的 Joshua Bloch 单元素枚举类型是实现单例的最佳方式。

这种方法有很多好处,你可以找到here
还有For instance control, prefer enum types to readResolve