As we’ve learned about serialization we’ve discussed how the JVM defines a default way to serialize objects when their classes implement the Serializable interface. Can we modify this default process? As a matter of fact we can by implementing the methods readObject() and writeObject() in our class!

Let’s look at some code that implements readObject() and writeObject():

public class DateOfBirth { private int month; private int day; private int year; // constructors and getters } public class Person implements Serializable { private String name; private DateOfBirth dateOfBirth; private void writeObject(java.io.ObjectOutputStream stream) throws IOException{ stream.writeObject(this.name); stream.writeInt(this.dateOfBirth.getMonth()); stream.writeInt(this.dateOfBirth.getDay()); stream.writeInt(this.dateOfBirth.getYear()); } private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException{ this.name = (String) stream.readObject(); int month = (int) stream.readInt(); int day = (int) stream.readInt(); int year = (int) stream.readInt(); this.dateOfBirth = new DateOfBirth(month, day, year); } }

In the example above:

  • We’ve got two classes Person which implements Serializable and DateOfBirth which does not.
  • Person has a reference field of type DateOfBirth.
  • If we were to use the default serialization process we would get a NotSeriliazableException because DateOfBirth does not implement Serializable.
  • We implement writeObject(), which must throw IOException, to serialize a DataOfBirth object by manually serializing all of its fields separately. We also serialize the serializable String field.
  • We implement readObject(), which must throw IOException and ClassNotFoundException, to deserialize a Person object by reading all the int fields that are a part of DataOfBirth and creating a new DateOfBirth object with the provided constructor. This new object is used to set the dateOfBirth field in Person.

Most times the default process of serialization is enough as long as all references implement Serializable. The implementation of readObject() and writeObject() is especially useful when you have a reference field that does not or cannot implement Serializable. You could also potentially handle static field values if you needed to persist them but this is not a good practice as a static field should belong to a class and not an object.

Let’s practice implementing our own custom serialization and deserialization methods.



The class Car has a non serializable Engine reference field named engine and cannot be serialized currently. Lets fix that!

In the class Car, complete the implementation of writeObject() to serialize the fields (state) of engine using the ObjectOutputStream stream methods. Use the provided public getters to access engine fields.


We’ve customized the serialization of a non serializable field in Car and we need to be able to desirialize Engine fields back into an engine object.

In the class Car, complete the implementation of readObject() to desirialize all Car fields using the ObjectInputStream stream methods. Create local double variable named liters and int cylinders to store the serialized Engine fields. Use the provided Engine constructor to initialize the engine reference field with liters and cylinders.

Take this course for free

Mini Info Outline Icon
By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.

Or sign up using:

Already have an account?