Question

package p1;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;


public class SerializationCheck {
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
        SingletonCompanyCEO s1 = SingletonCompanyCEO.getSingleObject();
        SingletonCompanyCEO s2 = SingletonCompanyCEO.getSingleObject();
        System.out.println("s1==s2:"+(s1==s2));

        ObjectOutputStream obs = new ObjectOutputStream(new FileOutputStream("file.txt"));
        obs.writeObject(s1);

        //first read from file
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file.txt"));
        SingletonCompanyCEO ceo = (SingletonCompanyCEO)ois.readObject();

        //second read from file 
        ois = new ObjectInputStream(new FileInputStream("file.txt"));
        SingletonCompanyCEO ceo1 = (SingletonCompanyCEO)ois.readObject();

        System.out.println("ceo==ceo1:"+(ceo==ceo1)+" (read from file ie. de-serialized )");
        System.out.println(ceo1);


    }
}

class SingletonCompanyCEO implements Serializable
{
    public void setName(String name){
        this.name = name;
    }
    public Object readResolve() throws ObjectStreamException {
        return singleObject;
    }
    private static final long serialVersionUID = 1L;
    private transient int age = 55; // age should set to zero by default as age is transient. But it is not happening, any reason?
    private String name ="Amit";
    float salary = 0f;

    private static SingletonCompanyCEO singleObject;
    private SingletonCompanyCEO()
    {
        if(singleObject!=null)
        {
            throw new IllegalStateException();
        }
    }
    public static SingletonCompanyCEO getSingleObject()
    {
        if(singleObject==null)
        {
            singleObject = new SingletonCompanyCEO();
        }
        return singleObject;
    }
    public String toString()
    {
        return name+" is CEO of the company and his age is "+
        age+"(here 'age' is transient variable and did not set to zero while serialization)";
    }
}

copy and paste this code in eclipse editor. What is the reason where 'age' transient variable is not set to zero by default while serialization?
Serialization says that transient and static variable are set to zero(or default values) while serialization.
After de-serialization I am getting age = 55 instead of age = 0.
There must be reason behind this in JLS. What is it?

Était-ce utile?

La solution

Any time a SingletonCompanyCEO object is deserialized, all information obtained from the ObjectInputStream is discarded and instead your singleObject is returned, due to your readResolve method. singleObject is itself an instance which was created using the constructor, not deserialization, so its age is 55.

Autres conseils

You are providing a static SingletonCompanyCEO object using getSingleObjectmethod. So your following reference variables of SingletonCompanyCEO i.e s1 , s2 are sharing the same SingletonCompanyCEO object. For this unique object you have following value for fields:

age = 55; 
name ="Amit";
salary = 0f;

But you have also overridden readResolve method in SingletonCompanyCEO class where you are returning the same object to which s1 and s2 are referencing. So while deserializing the class JVM makes the variable ceo and ceo1 to reference the same object to which s1 and s2 are referencing. So basically you have a single object of SingletonCompanyCEO class before serialization and after deserialization. That's why the age is printing as 55 .

UPDATE:
Here are the steps that is involving in your code after readResolve is removed in your code :

  1. JVM reads the Object from "file.txt" After object is read JVM looks for readResolve method in class SingletonCompanyCEO. JVM does not find readResolve and returns the new object to ceoas returned by deserialization.
  2. JVM again reads the object from "file.txt". After object is read JVM looks for readResolve method in class SingletonCompanyCEO. JVM does not find readResolve and returns the new object to ceo1 as returned by deserialization.

Hence after two deserialization you have two new objects of SingletonCompanyCEO.
=> ceo==ceo1 returns false.
NOTE: In both newly created objects value of age will be 0 as specified by JLS.

UPDATE2
if you comment writeobject parts of code and deserialize the class using already existing file (file.txt) Then following steps takes place while deserialization:

  1. JVM reads the object from the file using ObjectInputStream. After the object is read JVM looks for readResolve() method in SingletonCompanyCEO class. JVM returns only that object to the variable which is returned by readResolve() method defined in class.
  2. JVM finds the readResolve() method. In readResolve() method you had returned singleObject which is null for now as the method getSingleObject() is still not called up. And for your information, the constructor of class is also not called while deserialization , else it would have thrown IllegalstateException as you have done in constructor.
  3. Since readResolve() is returning null Hence JVM is also returning null . Consequenty ceo1 and ceo2 both are null .
private transient int age = 55;

When you define a value at declaration, this takes priority.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top