为什么我得到java.io.EOFException

时间:2013-12-22 02:05:18

标签: java serialization deserialization

如果我有一个带有嵌套类的类并且我将其序列化,那么如何从其中一个嵌套类中读取数据?

我知道如何从主类中读取这样的内容:

FileInputStream fis = new FileInputStream(eventsFile); 
ObjectInputStream ois = new ObjectInputStream(fis);  

GreenhouseControls gc = (GreenhouseControls) ois.readObject();

但是我尝试从这样的嵌套类中读取:

WindowMalfunction ce = (WindowMalfunction)ois.readObject();

我得到了这个例外:

java.io.EOFException
    at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at greenhouse.GreenhouseControls$Restore.action(GreenhouseControls.java:348)
    at other.Controller.run(Controller.java:45)
    at greenhouse.GreenhouseControls.main(GreenhouseControls.java:555)

当我序列化GreenhouseControls类时,我这样做了:

public void saveState() {
      try{
          // Serialize data object to a file
          ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("dump.out"));
          out.writeObject(GreenhouseControls.this);
          out.close();
          } catch (IOException e) {
          }
  }

2 个答案:

答案 0 :(得分:2)

类和其他方法不会被序列化。序列化是将对象转换为流的过程。

如果您的问题是“我如何序列化/反序列化嵌套类”,只需使嵌套类可序列化,然后像使用顶级类一样使用它。

如果您的问题是“我如何从序列化类访问嵌套类,您可以这样做:

((GreenhouseControls) ois.readObject()).new WindowMalfunction(<constructor arguments>);

答案 1 :(得分:1)

首先,正如@ user1549476所说,writeObject序列化对象。不是课程。这意味着:

  • 类的类/方法未序列化,
  • 类的状态(即静态值)未序列化。

其次,具有嵌套/内部/匿名内部类的类不是容器。

  • 对于内部和匿名内部类,存在从内部类实例到外部类实例的单向关系。但没有反向关系。这意味着无法从外部实例中找到所有内部实例。

  • 对于嵌套类,根本没有任何关系。

所以你想做的事情根本没有意义。并且发生EOF异常是因为您正在尝试回读未首先写入的对象。


如果希望外部类实例充当容器,则需要将实例属性添加到包含对内部类实例的引用的外部类。然后,您需要实施“容器管理”操作。如果这样做,并确保外部和内部类是可序列化的,那么序列化外部实例将序列化其容器数据结构中的内部实例。


对于嵌套类(但不是内部类!),您可以使类可序列化并独立存储实例。

对于内部类,序列化需要包含外部类,但我认为这将自动发生。例如,如果有这样的事情:

  Outer outer = ...
  Inner inner1 = outer.new Inner(...);
  Inner inner2 = outer.new Inner(...);
  ...
  ObjectOutputStream oos = ...
  oos.writeObject(inner1);
  oos.writeObject(inner2);
  oos.close();
  ...
  ObjectInputStream ois = ...
  Inner deserialized_inner1 = (Inner) ois.readObject();
  Inner deserialized_inner2 = (Inner) ois.readObject();

...你应该获取一对Inner个实例,其“外部”是刚刚被反序列化的Outer实例!