繁体   English   中英

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

[英]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;
    }
}

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

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

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

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

  1. 静态常量与该类相关联,因此实例的序列化和反序列化完全不会对其产生影响。

  2. 为了使反序列化起作用,您需要将单例的数据设置为反序列化的实例数据:

     private Object readResolve() throws ObjectStreamException { instance.setData(getData()); return instance; } 
  3. 时间戳记可以保持为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 ,因为反序列化实例已覆盖当前实例。 serializedeserialize 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.

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