2013-02-20 73 views
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背后必有理由。它是什么?为什么瞬态变量的状态存储在单例对象中?

回答

1

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

0
private transient int age = 55; 

当你在声明中定义一个值时,这需要优先。

1

您正在使用getSingleObject方法提供静态的SingletonCompanyCEO对象。因此,您的以下参考变量SingletonCompanyCEOs1,s2共享相同的SingletonCompanyCEO对象。对于这种独特的对象,你已经为字段以下值:

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

但你也覆盖readResolve方法SingletonCompanyCEO类,你正在返回其s1s2都引用同一个对象。因此,反序列化类JVM会使变量ceoceo1引用与s1s2引用的对象相同的对象。所以基本上,在序列化之前和反序列化之后,您只有一个类为SingletonCompanyCEO的对象。这就是为什么age打印为55

UPDATE:
这里是被readResolve之后涉及您的代码中的步骤,您的代码被删除:

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

因此经过两次反序列化你有 SingletonCompanyCEO两个新的对象。
=> ceo == ceo1返回false。
注意:在两个新创建的对象中,根据JLS的规定,age的值将为0。

UPDATE2
如果你对此有何评论writeobject部分的代码,并使用已存在的文件(file.txt)那么下面的步骤反序列化类发生,而反序列化:

  1. JVM从文件中读取对象使用ObjectInputStream。 读取对象后,JVM在SingletonCompanyCEO类中查找readResolve()方法。 JVM仅将该对象返回到由类定义的readResolve()方法返回的变量。
  2. JVM找到了readResolve()方法。在readResolve()方法中,由于方法getSingleObject()仍未调用,因此您现在返回了singleObject,即null。而且,对于您的信息,类的构造函数在反序列化时也不会被调用,否则就像您在构造函数中所做的那样抛出IllegalstateException
  3. 由于readResolve()正在返回null因此JVM也返回null。因此,ceo1ceo2都是null
+0

同意。执行上面的代码,然后删除s1和s2引用创建的代码,并删除写入对象的代码。现在我们已经序列化了包含对象的文件。 删除后,我们只有文件阅读代码。现在我发现对象没有被创建,'null'正在读取文件后返回。现在再次尝试删除readResolve(),然后你会发现对象正在创建,而不是单身。它是什么? – AmitG 2013-02-21 08:22:28

+1

@AmitG:查看我的更新。 – 2013-02-21 08:50:01

+0

好的。同意。但是如果我们保持readResolve()方法,那么对象将从文件中变为'null'。怎么样? 如何反序列化Singleton对象,以便每个JVM只能获取实例? 如果我们保持readResolve()两个对象的创建,并且如果我们不保存readResolve(),则不会创建任何对象。 – AmitG 2013-02-21 10:36:34

相关问题