0

readResolve() is not called during deserialization of an enum object. The reason I am trying to do is to compare two ways of achieving Singleton.

Singleton can be implemented in two ways.

  1. Traditional way of static instance object and private constructor
  2. using Single object enum

Second way needs less coding.

I was comparing the the two approaches with respect to ways to override singleton behaviour and care to be taken by programmer

1) Cloning

In traditional way do not implement clonable interface or throw error in clone() method. In Enum way it is not needed as cloning is not possible as enum can not implement clonable method

2) Create object through reflection

In traditional way throw error in constructor if instance is already intialized. In Enum way it is not needed as we cannot reflectively create enum objects. It throws error " java.lang.IllegalArgumentException: Cannot reflectively create enum objects"

3) Serialization-deserialization

In traditional implement serializable interface or if implemented readResolve() method to return same instance.

Now in Enum are by default serializable. So I implemented the readResolve() however readResolve() is not called when deserialization is done. It automatically gave me the latest state of Enum object. Why is it so ?

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

Now in calling class I serialize MySingletonEnum.getInstance(). So what I have written is age=41 and name=Devendra.

Then change the properties of MySingletonEnum.getInstance() i.e. "Age" to 999 and "Name" to "Kaushik".

Then deserialize object.

The readResolve() method was not called. Still deserialized object has age=999 and 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");
    }
}

Output

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

Should it not show 41,Devendra ? How is it so ?

Kaushik Lele
  • 6,439
  • 13
  • 50
  • 76
  • How are you doing `Then change the properties of MySingletonEnum.getInstance() `this? – Naman Feb 26 '17 at 07:00
  • using setter methods of age and name – Kaushik Lele Feb 26 '17 at 07:02
  • 1
    Because the smart Java engineers already made sure that enums were not broken by serialization, and that each enum instance existed once and only once for a given ClassLoader. See http://stackoverflow.com/questions/15521309/is-custom-enum-serializable-too – JB Nizet Feb 26 '17 at 07:32

1 Answers1

4

Because:

  1. readResolve() methods are ignored for Enums.

  2. Enums already don't break the singleton pattern. You don't need to implement this yourself.

user207421
  • 305,947
  • 44
  • 307
  • 483