Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 单例设计模式的序列化_Java_Serialization_Deserialization - Fatal编程技术网

Java 单例设计模式的序列化

Java 单例设计模式的序列化,java,serialization,deserialization,Java,Serialization,Deserialization,我对使用singleton模式的类的序列化有问题。首先让我介绍一下代码: import java.io.ObjectStreamException; import java.io.Serializable; import org.ejml.simple.SimpleMatrix; public class Operation implements Serializable { private static final long serialVersionUID = 1L;

我对使用singleton模式的类的序列化有问题。首先让我介绍一下代码:

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;
    }
}
我有三个问题,希望有人能帮助我:

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

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

  • 在序列化之前,我将字段
    timestamp
    设置为序列化时间。反序列化后,我想将此字段与一些文件的时间戳进行比较(以查看自序列化以来文件是否发生了更改)。我应该为文件的序列化时间和上次修改时间使用什么样的时间戳,以便比较

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

  • 要使反序列化工作,需要将单例数据设置为反序列化的实例数据:

    private Object readResolve() throws ObjectStreamException {
        instance.setData(getData());
        return instance;
    }
    
  • 时间戳可以保持很长时间,这很好。使用System.currentTimeMillis(),您将能够与文件对象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
    ,因为反序列化实例已经覆盖了当前实例<代码>序列化
    反序列化
    只需在实例和字节之间进行转换。

    我建议您采用枚举单例方法来实现单例,因为处理序列化是免费的。在你的情况下是这样的

    public enum Operation {
        INSTANCE; 
        // No need to handle Serialization 
    }
    
    引用Joshua Bloch在《有效Java》中的话,“单元素枚举类型是实现单例的最佳方式。”

    这种方法有很多好处,您可以发现

    而且

    我也不太清楚为什么需要序列化singleton操作。但我建议:只序列化矩阵(这似乎是单例中唯一改变的事情),然后让单例正常构建。或者更好,不要使用单例,使用依赖注入;)@皮尔·亨利的手术只是一个例子。是的,只有矩阵改变了。如何只序列化矩阵,然后再将矩阵反序列化回singleton?@Pierrehrenry我还需要序列化时间戳。添加必要的逻辑作为singleton的方法:例如saveState和restoreState。或者在外面做,然后做setMatrix之类的。谢谢你的回答。关于第二点,我有一个问题。我是否还必须添加instance.setTimestamp(getTimestamp());如果我将时间戳设为私有并引入setter和getter?在我的帖子中看到我更改的代码。是的,当然,我在代码中没有这样做,但你也应该设置时间戳。