0
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)";
    }
}

将此代码复制并粘贴到 Eclipse 编辑器中。序列化时'age'transient变量默认不设置为零的原因是什么?
序列化表示瞬态和静态变量在序列化时设置为零(或默认值)。
反序列化后,我得到age = 55的不是age = 0.
在 JLS 中,这背后一定是有原因的。它是什么?

4

3 回答 3

1

您正在使用方法提供静态SingletonCompanyCEO对象getSingleObjectSingletonCompanyCEO因此,您的ies1的以下引用变量s2共享同一个SingletonCompanyCEO对象。对于这个独特的对象,您具有以下字段值:

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

但是您在类中也覆盖readResolve了方法SingletonCompanyCEO,您在其中返回s1s2引用的相同对象。因此,在反序列化类时,JVM 会生成变量ceo并引用和ceo1引用的同一对象。所以基本上你在序列化之前和反序列化之后都有一个类的对象。这就是为什么打印为.s1s2SingletonCompanyCEOage55

更新:以下是在您的代码中删除
后涉及您的代码的步骤:readResolve

  1. JVM 从“file.txt”中读取对象 读取对象后 JVMreadResolve在类中查找方法SingletonCompanyCEO。JVM 没有找到新对象并返回到反序列readResolve化返回的对象。ceo
  2. JVM 再次从“file.txt”中读取对象。读取对象后,JVM 会readResolve在类中查找方法SingletonCompanyCEO。JVM 没有找到新对象并返回到反序列readResolve化返回的对象。ceo1

因此,在两次反序列化之后,您有两个新的 SingletonCompanyCEO.
=> ceo==ceo1 返回错误。
注意:在两个新创建的对象中age,JLS 指定的值为 0。

UPDATE2
如果您注释writeobject部分代码并使用已经存在的文件(file.txt)反序列化类,那么在反序列化时会执行以下步骤:

  1. JVM 使用 ObjectInputStream 从文件中读取对象。读取对象后,JVM 会在类中查找readResolve()方法。SingletonCompanyCEOJVM 仅将该对象返回给由readResolve()类中定义的方法返回的变量。
  2. JVM 找到该readResolve()方法。在readResolve()您返回的方法singleObjectnull,目前该方法getSingleObject()仍未被调用。并且为了您的信息,在反序列化时也不会调用类的构造函数,否则它会IllegalstateException像您在构造函数中所做的那样抛出。
  3. 由于readResolve()正在返回null因此 JVM 也正在返回null。结果ceo1ceo2两者都是null
于 2013-02-20T19:32:23.057 回答
1

每当反序列化 SingletonCompanyCEO 对象时,从 ObjectInputStream 获得的所有信息都将被丢弃,而是返回您的 singleObject,这取决于您的readResolve方法。singleObject 本身就是一个使用构造函数创建的实例,而不是反序列化,所以它的年龄是 55。

于 2013-02-21T12:59:30.190 回答
0
private transient int age = 55;

当您在声明时定义一个值时,这具有优先权。

于 2013-02-20T17:16:59.710 回答