【问题标题】:Why is the first constructor called after deserialization and no others为什么反序列化后调用第一个构造函数而没有其他构造函数
【发布时间】:2012-09-07 11:17:46
【问题描述】:

请有人解释一下为什么反序列化后调用了“Gambler”类的构造函数,但说“Player”类的构造函数没有调用?

import java.io.*;
  class Gambler {
   Gambler() { System.out.print("d"); }
  }
  class Person extends Gambler implements Serializable {
   Person() { System.out.print("c"); }
  }
  class Player extends Person {
   Player() { System.out.print("p"); }
 }

  class CardPlayer extends Player implements Serializable {
    CardPlayer() { System.out.print("c"); }
      public static void main(String[] args) {
      CardPlayer c1 = new CardPlayer();
      try {
            FileOutputStream fos = new FileOutputStream("play.txt");
            ObjectOutputStream os = new ObjectOutputStream(fos);
            os.writeObject(c1);
            os.close();
            FileInputStream fis = new FileInputStream("play.txt");
            ObjectInputStream is = new ObjectInputStream(fis);
            CardPlayer c2 = (CardPlayer) is.readObject();
            is.close(); 

            } 
      catch (Exception x ) { }
 }
}

【问题讨论】:

  • 因为这是对象序列化规范中的强制要求?

标签: java serialization


【解决方案1】:

因为Gambler 类没有实现Serializable 接口。来自Serializable的javadocs:

为了允许序列化不可序列化类的子类型,子类型可能会负责保存和恢复超类型的公共、受保护和(如果可访问)包字段的状态。仅当它扩展的类具有可访问的无参数构造函数来初始化类的状态时,子类型才可以承担此责任。如果不是这种情况,则声明类 Serializable 是错误的。将在运行时检测到错误。

在反序列化期间,不可序列化类的字段将使用类的公共或受保护的无参数构造函数进行初始化。可序列化的子类必须可以访问无参数构造函数。 可序列化子类的字段将从流中恢复。

请参阅java.io.Serializable java docs

【讨论】:

  • 谢谢,我相信这是解决方案
【解决方案2】:

serializing Object Tree is persisted 在您的案例中,对象树最多为 Person 类。 现在Super() 机制出现在如果父类对于任何子类都不可序列化的情况下。所以这就是你的Gambler 的构造函数被调用的原因。

您可以在http://docs.oracle.com/javase/6/docs/api/java/io/Serializable.html找到更多信息

在反序列化期间,不可序列化类的字段将使用类的公共或受保护的无参数构造函数进行初始化。可序列化的子类必须可以访问无参数构造函数。可序列化子类的字段将从流中恢复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    相关资源
    最近更新 更多