1

Why I don't have an error while I am trying to read Child class into Parent's class variable? I thought that before asigning object that have been read compiler checks serialVersionUID of both classes (variable class and class that have been read) and if serialVersionUID is not equal InvalidClassException is thrown. So does A class and B class have the same 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();
    }
}
Denys_newbie
  • 1,140
  • 5
  • 15
  • Does this answer your question? [When should we implement Serializable interface?](https://stackoverflow.com/questions/4548816/when-should-we-implement-serializable-interface) – K.Nicholas Jan 09 '21 at 16:26

1 Answers1

2

No, these two classes do not have the same serialVersionUID. There is no exception thrown because class B can be reconstructed successfully. There would for example be an InvalidClassException when the serialVersionUID would not match or when A would not implement a default constructor.

When you deserialise with objectInputStream.readObject(), an Object is returned which can be cast safely to B. Since B extends A, it can be upcasted to an object of type A – as it happens in your code.

On a sidenote, I strongly suggest that you define a serialVersionUID for your classes if you are directly storing and retrieving objects using serialisation.


You can get the serialVersionUID of the two classes as follows:

ObjectStreamClass.lookup(A.class).getSerialVersionUID()
ObjectStreamClass.lookup(B.class).getSerialVersionUID()
Matt
  • 12,848
  • 2
  • 31
  • 53
  • I got this, but how JVM knows which class I want to deserialize? I mean why ```objectInputStream.readObject()``` return exactly ```B``` class if it see only ```serialVersionUID```? – Denys_newbie Jan 09 '21 at 17:11
  • @Denis_newbie The metadata is stored in the serialised stream according to the [Grammar for the Stream Format](https://docs.oracle.com/javase/8/docs/platform/serialization/spec/protocol.html#a10258). This includes the full classname including package after the `TC_CLASSDESC` constant. You can have a look at the stored file (`b.bin`) and inspect it's content. An option would be `hexdump -C b.bin`. – Matt Jan 09 '21 at 18:03