【发布时间】:2017-07-16 20:59:44
【问题描述】:
readResolve() 在枚举对象的反序列化期间不会被调用。 我尝试这样做的原因是比较两种实现 Singleton 的方法。
单例可以通过两种方式实现。
- 静态实例对象和私有构造函数的传统方式
- 使用单个对象枚举
第二种方式需要更少的编码。
我正在比较这两种方法来覆盖单例行为和程序员需要注意的方式
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