IUnknown
IUnknown

Reputation: 9839

transient for serializing singleton

Effective Java - To maintain the singleton guarantee, you have to declare all instance fields transient and provide a 'readResolve' method. What do we achieve by declaring the fields transient here? Here's a sample:

....
....
public final class MySingleton implements Serializable{
 private int state;
 private MySingleton() { state =15; }
 private static final MySingleton INSTANCE = new MySingleton();
 public static MySingleton getInstance() { return INSTANCE; }
 public int getState(){return state;}
public void setState(int val){state=val;}
private Object readResolve() throws ObjectStreamException {
  return INSTANCE; 
 }
    public static void main(String[] args) {
        MySingleton  c = null;
        try {
            c=MySingleton.getInstance();
            c.setState(25);
            FileOutputStream fs = new FileOutputStream("testSer.ser");
            ObjectOutputStream os = new ObjectOutputStream(fs);
            os.writeObject(c);
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            FileInputStream fis = new FileInputStream("testSer.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            c = (MySingleton) ois.readObject();
            ois.close();
            System.out.println("after deser: contained data is " + c.getState());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

Irrespective of whether I declare the 'state' variable as transient or not ,I get c.getState() gettign printed out as 25. Am I Missing something here?

Upvotes: 0

Views: 1183

Answers (3)

TheMonkWhoSoldHisCode
TheMonkWhoSoldHisCode

Reputation: 2332

try {
            c=MySingleton.getInstance();
            c.setState(25);
            FileOutputStream fs = new FileOutputStream("testSer.ser");
            ObjectOutputStream os = new ObjectOutputStream(fs);
            os.writeObject(c);
            os.close();
 }

You are getting 25 because you are setting that value in the object. Refer above code. I think you were expecting the answer to be 15?

Upvotes: 0

lunatikz
lunatikz

Reputation: 736

Irrespective of whether I declare the 'state' variable as transient or not ,I get c.getState() gettign printed out as 25. Am I Missing something here?

You replace your deserialized object, because readResolve() returns the private static instance of MySingleton, thus overriding the instance returned by the deserialization.

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 692231

What you gain by making the attribute transient is that you don't serialize the state. Serializing it is unnecessary, since it's discarded anyway by the readResolve() method.

If the state consists in an int, it doesn't matter much. But if the state is a complex graph of objects, it makes a significant performance difference. And of course, if the state is not serializable, you don't have any other choice.

That said, serializing a singleton is questionable.

Upvotes: 3

Related Questions