Java 为什么在父类中反序列化时不引发InvalidClassException

Java 为什么在父类中反序列化时不引发InvalidClassException,java,serialization,deserialization,Java,Serialization,Deserialization,为什么我在尝试将子类读入父类变量时没有错误? 我认为在指定已读取的对象之前,编译器会检查两个类(变量类和已读取的类)的serialVersionId,如果serialVersionId不相等,则会抛出InvalidClassException。那么A类和B类是否具有相同的serialVersionUID import java.io.*; class A {} class B extends A implements Serializable {} public class Test {

为什么我在尝试将子类读入父类变量时没有错误? 我认为在指定已读取的对象之前,编译器会检查两个类(变量类和已读取的类)的
serialVersionId
,如果
serialVersionId
不相等,则会抛出
InvalidClassException
。那么
A
类和
B
类是否具有相同的
serialVersionUID

import java.io.*;

class A  {}

class B extends A implements Serializable {}

public class Test
{
    public static void main(String[] args) throws IOException, ClassNotFoundException
    {
        FileOutputStream fileOutputStream = new FileOutputStream("b.bin");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        B b1 = new B();
        objectOutputStream.writeObject(b1);
        objectOutputStream.close();
        
        FileInputStream fileInputStream = new FileInputStream("b.bin");
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        A a1 = (A) objectInputStream.readObject(); // why I don't have an InvalidClass Exception here
        objectInputStream.close();
    }
}

不,这两个类没有相同的
serialVersionUID
。没有引发异常,因为类
B
可以成功重建。例如,当
serialVersionUID
不匹配或
A
不实现默认构造函数时,就会出现InvalidClassException

使用
objectInputStream.readObject()
反序列化时,将返回一个
对象
,该对象可以安全地强制转换到
B
。由于
B
扩展了
A
,因此可以将其向上转换为
A
类型的对象,就像在代码中发生的那样

另一方面,如果您使用序列化直接存储和检索对象,我强烈建议您为类定义一个
serialVersionUID


您可以获得这两个类的
serialVersionUID
,如下所示:

ObjectStreamClass.lookup(A.class).getSerialVersionUID()
ObjectStreamClass.lookup(B.class).getSerialVersionUID()

这回答了你的问题吗?我知道了,但是JVM怎么知道我要反序列化哪个类呢?我的意思是,如果只看到
serialVersionUID
,为什么
objectInputStream.readObject()
会准确返回
B
类?@Denis\u newbie元数据根据。这包括
TC\u CLASSDESC
常量后的完整类名,包括包。您可以查看存储的文件(
b.bin
)并检查其内容。一个选项是
hextump-cb.bin