【问题标题】:Basics of Serialization in java not understoodjava中序列化的基础知识不明白
【发布时间】:2013-08-20 10:09:43
【问题描述】:

我无法理解 Java 1.6 中 Serialization 的基础知识。

下面是Dog 类,其中包含Collar 类的实例变量:

Dog.java

public class Dog implements Serializable {

private Collar collar;

public Collar getCollar() {
    return collar;
}

public void setCollar(Collar collar) {
    this.collar = collar;
}

}

Collar类没有实现Serializable接口如下图:

Collar.java

public class Collar {

private int size;

public int getSize() {
    return size;
}

public void setSize(int size) {
    this.size = size;
}

}

现在,当我尝试序列化 Dog 时,为什么它不抛出 NotSerializableException ?根据合同,整个对象图应该实现Serializable,但我的Collar 类没有实现。

下面是这个demo的主要方法:

public static void main(String[] args) {
    try {
        FileOutputStream fs = new FileOutputStream("E:\\test.ser");
        ObjectOutputStream os = new ObjectOutputStream(fs);
        Dog dog = new Dog();
        // No exception thrown here, WHY?
        // test.ser file is getting created properly.
        os.writeObject(dog);

        FileInputStream fis = new FileInputStream("E:\\test.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Dog dog1 = (Dog)ois.readObject();
        // Here I am getting a null Collar object
        Collar c1 = dog1.getCollar();

请解释一下,在尝试实现所有理论内容时我完全感到困惑:(

【问题讨论】:

  • 请在阅读文件之前添加这些行outputStream.flush();outputStream.close();,然后报告您的发现
  • 您自己说过:整个对象图必须是可序列化的,而不是您的代码碰巧提到的所有类。
  • @Multithreader 如果我添加上面提到的两行,没有发现差异
  • 好吧,您的整个对象图只是Dog 对象本身。它不包含对任何其他对象的引用。如果您将 setCollar 与非空参数一起使用,那么您将扩展对象图以包含该对象,并获得您期望的异常。
  • @WhoAmI 当您写信给OutputStream 时,您需要.close() 它(它会执行.flush() 甚至可能更多 - 不需要两者都执行)以确保任何缓冲的数据实际上是书面。没有你可能永远不会写最后几个字节,因此会读取损坏的数据。对于文件输出,您可能还需要同步:stackoverflow.com/questions/4072878/i-o-concept-flush-vs-sync

标签: java servlets web-applications serialization serializable


【解决方案1】:

可能是因为您的dog 没有collar

试试

Dog dog = new Dog();
dog.setCollar(new Collar());

【讨论】:

  • 有趣。所以序列化是关于实例化的类,而不是它们的声明。回想起来,这是有道理的,因为我们可以用 Accessory 替换 Collar,并让 Collar 和 FoodBowl 成为 Accessory 的实现者。附件不值得序列化 - 我们需要实际的具体类。
【解决方案2】:

看来您对对象图的概念有误解。在此图中,节点是实例不是类),边是由引用类型的实例变量的值形成的。

应用于您的示例,

Dog dog = new Dog();

创建一个由单个节点组成的对象图,Dog 实例。 collar 变量是 null,因此它的值不会形成边缘,也不会形成另一个节点。但是,如果您添加一行,例如

dog.setCollar(new Collar());

现在您的对象图包含两个节点,由 collar 实例变量中的值形成的边连接。

现在,所有这些都应用于序列化意味着您发布的示例正在序列化单节点对象图,其所有节点都是可序列化的,但是如果您添加一个衣领,该图将包含一个非序列化节点,您会得到您期望的异常。

【讨论】:

    猜你喜欢
    • 2017-08-12
    • 1970-01-01
    • 2011-06-01
    • 2014-06-19
    • 2013-03-23
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多