【问题标题】:How serialization works when only subclass implements serializable当只有子类实现可序列化时,序列化如何工作
【发布时间】:2012-12-26 15:02:20
【问题描述】:

只有子类实现了Serializable接口。

import java.io.*;

public class NewClass1{

    private int i;
    NewClass1(){
    i=10;
    }
    int getVal() {
        return i;
    }
    void setVal(int i) {
        this.i=i;
    }
}

class MyClass extends NewClass1 implements Serializable{

    private String s;
    private NewClass1 n;

    MyClass(String s) {
        this.s = s;
        setVal(20);
    }

    public String toString() {
        return s + " " + getVal();
    }

    public static void main(String args[]) {
        MyClass m = new MyClass("Serial");
        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("serial.txt"));
            oos.writeObject(m); //writing current state
            oos.flush();
            oos.close();
            System.out.print(m); // display current state object value
        } catch (IOException e) {
            System.out.print(e);
        }
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("serial.txt"));
            MyClass o = (MyClass) ois.readObject(); // reading saved object
            ois.close();
            System.out.print(o); // display saved object state
        } catch (Exception e) {
            System.out.print(e);
        }
    }
}

我在这里注意到的一件事是,父类没有序列化。那么,为什么不抛出NotSerializableException 确实是在显示关注

输出

Serial 20
Serial 10

此外,输出不同于SerializationDe-serialization。我只知道,是因为父类没有实现Serializable。但是,如果有人向我解释,对象序列化和反序列化期间会发生什么。它如何改变价值?我无法弄清楚,我也在我的程序中使用了注释。所以,如果我在任何时候错了,请告诉我。

【问题讨论】:

    标签: java inheritance serialization deserialization notserializableexception


    【解决方案1】:

    根据Serializable javadoc

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

    此外,仅当被序列化的类不可序列化时才会引发序列化异常。拥有不可序列化的父母很好(只要他们有一个无参数的构造函数)。对象本身不是可序列化的,并且一切都扩展了它。 上面的引用还解释了为什么您会为 value 字段获得不同的值 - 父类的无参数构造函数已设置,它将 value 字段设置为 10 - 该字段属于(不可序列化的)父级,因此它的值不是写入/读取流。

    【讨论】:

      【解决方案2】:

      如果您的 MyClass 持有对不可序列化类对象的引用,您将在运行时获得 NotSerializable 异常。要进行测试,请修改 MyClass,使其包含对 NewClass1 对象的引用。如果你再次运行它会抛出一个异常。

      反序列化本质上是创建可序列化类的实例并恢复其属性。在此过程中,不调用可序列化类的构造函数。而是调用第一个不可序列化超类的无参数构造函数。

      在您的情况下,NewClass1 的无参数构造函数将 10 分配给其实例变量 i。因此,在反序列化期间,它打印的是 10 而不是 20。

      【讨论】:

      • 是的,它会的。这就是为什么,我的问题不是那个。我已经改变了原来的代码。请浏览我的代码。
      • 我的问题不完全是,为什么我的代码没有显示NotSerializableException??而是我在问,这些输出有何不同,当前代码中的序列化和反序列化背景。
      • 在我的回答中添加了更多信息。希望对你有帮助。
      【解决方案3】:

      我还没有测试过,但是如果序列化基类的实例,你会得到一个NotSerializableException。当您的类包含一些不是Serializable 的成员时也是如此。

      意味着如果你创建一个对象NewClass1 nc1 = new NewClass1(); 并尝试序列化obj nc1,你会得到你想要的异常。

      【讨论】:

      • 是的,在这种情况下,我得到NotSerializableException,但在当前情况下没有。请浏览我的代码。
      • 嗯...我明白你想挖掘什么。您当前的方案有效,因为您在基类中有一个默认构造函数。在这种情况下,JVM 不太智能,只是忽略了基类中存在的 int。在反序列化时,它会调用默认构造函数。如果你在基类的构造函数中添加一个婴儿车,对象仍然会被序列化,但我猜你在反序列化时会得到一个异常。
      猜你喜欢
      • 2016-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 2011-12-01
      • 1970-01-01
      • 2016-08-30
      相关资源
      最近更新 更多