【问题标题】:readResolve() not called during Enum desrialization在枚举反序列化期间未调用 readResolve()
【发布时间】:2017-07-16 20:59:44
【问题描述】:

readResolve() 在枚举对象的反序列化期间不会被调用。 我尝试这样做的原因是比较两种实现 Singleton 的方法。

单例可以通过两种方式实现。

  1. 静态实例对象和私有构造函数的传统方式
  2. 使用单个对象枚举

第二种方式需要更少的编码。

我正在比较这两种方法来覆盖单例行为和程序员需要注意的方式

1) 克隆

在传统方式中不要实现可克隆接口或在 clone() 方法中抛出错误。 在枚举方式中,不需要克隆,因为枚举无法实现可克隆方法

2) 通过反射创建对象

如果实例已经初始化,则以传统方式在构造函数中抛出错误。 在 Enum 方式中,它是不需要的,因为我们不能反射地创建枚举对象。它抛出错误“java.lang.IllegalArgumentException:无法反射地创建枚举对象”

3)序列化-反序列化

在传统实现可序列化接口或如果实现 readResolve() 方法返回相同的实例。

现在在 Enum 中默认是可序列化的。所以我实现了 readResolve() 但是当反序列化完成时没有调用 readResolve() 。 它自动给了我 Enum 对象的最新状态。 为什么会这样?

public enum MySingletonEnum {
instance(41,"Devendra");

private MySingletonEnum(int age, String name){
        this.age = age;
        this.name = name;
}

private int age;
private String name;
// getters and setters

public static MySingletonEnum getInstance(){
    return instance;
}

  //Hook for not breaking the singleton pattern while deserializing.
private Object readResolve() throws ObjectStreamException {
    System.out.println("The constructed obejct has age="+age+" name="+name);
    System.out.println("But now returning same instance");
      return instance;
}
}

现在正在上课 我序列化 MySingletonEnum.getInstance()。所以我写的是age=41和name=Devendra。

然后将 MySingletonEnum.getInstance() 的属性,即“Age”更改为 999,将“Name”更改为“Kaushik”。

然后反序列化对象。

未调用 readResolve() 方法。仍然反序列化的对象有 age=999 和 Name=Kaushik。

public static void  trySerialization() throws FileNotFoundException, IOException, ClassNotFoundException{
    String filePath = "d:\\kaushik\\kaushik26Feb.txt";
    File f = new File(filePath);
    f.createNewFile();

    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
    oos.writeObject(MySingletonEnum.getInstance());
    oos.close();
    MySingletonEnum.getInstance().setAge(999);
    MySingletonEnum.getInstance().setName("Kaushik");
    System.out.println("Printing values before deserialize");
    MySingletonEnum.getInstance().print();
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
    MySingletonEnum deserializedObj = (MySingletonEnum)ois.readObject();

    System.out.println("deserializedObj="+deserializedObj);
    System.out.println(deserializedObj.getAge()+" ...."+deserializedObj.getName());

    if(deserializedObj==MySingletonEnum.getInstance()){
        System.out.println("Same instance");
    }else{
        System.out.println("Different instance");
    }
}

输出

Printing values before deserialize
999 ....Kaushik
deserializedObj=instance
999 ....Kaushik
Same instance

不应该显示 41,Devendra 吗? 怎么会这样?

【问题讨论】:

  • 你好吗Then change the properties of MySingletonEnum.getInstance() this?
  • 使用年龄和姓名的setter方法
  • 因为聪明的 Java 工程师已经确保枚举不会被序列化破坏,并且每个枚举实例对于给定的 ClassLoader 只存在一次。见stackoverflow.com/questions/15521309/…

标签: java serialization enums singleton deserialization


【解决方案1】:

因为:

  1. readResolve() methods are ignored for Enums.

  2. Enums 已经不破坏单例模式。你不需要自己实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    • 2019-05-31
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    相关资源
    最近更新 更多