【问题标题】:Child Class is Serializable into a file, but the file is not Deserializable子类可序列化成文件,但文件不可反序列化
【发布时间】:2022-01-13 18:39:53
【问题描述】:

我们有一个名为“Vehicle”的超类,它实现了标记接口 Serializable。 然后我们有一个名为“Car”的子类,它继承了“Vehicle”,因此子类“Car”也实现了Serializable标记接口,因为它是父“Vehicle”。

现在我们可以将任何车辆实例序列化为文件,而不会出现任何问题。 但是当我们尝试将该文件反序列化为“汽车”类型的对象时,程序会抛出异常。

我解决这个问题的方法是在“Car”类中手动实现 Serializable 标记接口。

为什么会这样?从我今天阅读的关于序列化的所有内容来看,似乎没有人涉及这个问题。

我得出的结论是:“Car”类在继承“Vehicle”类的同时,也继承了“Vehicle”中实现的接口,因此“Car”对象是可序列化的,但是一旦我们序列化一个将“Car”对象的实例复制到文件(例如:“car1.ser”),“car1.ser”文件中写入了一个对象,其中包含所有的修饰符、属性、方法等。 但不知何故,写入“car1.ser”文件的“Car”类型的对象并没有从它的父级继承“Serializable”标记。这是什么原因,我不太确定。

【问题讨论】:

    标签: java serialization deserialization


    【解决方案1】:

    什么例外? (请考虑将其添加到帖子中,因为这似乎是一个“重要的细节”)

    对不起,无法再现/理解:

    package com.example.serial;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    public class SerialTest {
    
      public static void main(String[] args) throws IOException, ClassNotFoundException {
        Car car = new Car();
        car.manufacturer = "Toyota";
        car.model = "Land Cruiser";
        
        // tmp memory:
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    
        // write object:
        ObjectOutputStream oos = new ObjectOutputStream(outStream);
        oos.writeObject(car);
    
        // input stream of "tmp memory":
        ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
    
        // read object:
        ObjectInputStream ois = new ObjectInputStream(inStream);
        Car c2 = (Car) ois.readObject();
    
        // print/verify:
        System.out.println(c2);
      }
    }
    
    class Vehicle implements Serializable {
    
      private static final long serialVersionUID = 0L;
      String manufacturer;
    }
    
    class Car extends Vehicle {
    
      String model;
    }
    

    打印:

    com.example.serial.Car@1ed6993a
    

    我们也可以这样做:

    Vehicle car = new Car();
    // ... same code, but without "model"
    

    但不是:

    Vehicle car = new Vehicle();
    ...
    

    ..这将导致:

    java.lang.ClassCastException: class com.example.serial.Vehicle cannot be cast to class com.example.serial.Car
    

    在这一行:

    Car c2 = (Car) ois.readObject();
    

    参考:https://docs.oracle.com/en/java/javase/17/docs/specs/serialization/serial-arch.html

    【讨论】:

    • 明天我会将整个项目发布在 GitHub 上,并将链接留在我的帖子中。我可能有臭代码。无论如何,我得到的异常是“InvalidClassException”。
    • 首先感谢您的回答,您确实花时间写了它,其次我真的很抱歉。我再次彻底查看了我的代码,问题是一个非常愚蠢的问题,我的文件位置有一个错字。
    • 很高兴您找到了错字……但仍然是 InvalidClassException? "当序列化运行时检测到类的以下问题之一时抛出。 1. 类的 序列版本 与从流中读取的类描述符的版本不匹配 2. 类包含 未知数据类型 3.类没有可访问的无参数构造函数”来自java7
    • until java 17 另外:“4.枚举常量的ObjectStreamClass不代表枚举类型 5.其他条件在Java 对象序列化规范"
    • 所以我写了: ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("car1.txt"));应该是:ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("car1.ser"));
    猜你喜欢
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 2022-01-18
    • 2021-12-21
    相关资源
    最近更新 更多