ObjectInputStream and ObjectOutputStream

Naveen AnamaneniUpdated · 3 min read
mediumJava 25javaioserialization

ObjectOutputStream and ObjectInputStream are wrapper streams used to write whole Java objects to a stream and read them back, a process called serialization and deserialization. Where a data stream writes one int or double at a time, an object stream writes an entire object, including its fields and the other objects it refers to, with one call to writeObject. The object's class must implement the Serializable interface. This lesson introduces object streams; the full details are covered in "Serialization and Deserialization in Java".

Methods

MethodDescription
ObjectOutputStream.writeObject(Object o)It is used to serialize an object and everything it refers to.
ObjectInputStream.readObject()It reads an object back; you cast it to the right type.
writeInt, readInt, writeUTF...It reads and writes primitives too, like data streams.

Example: Saving and Loading a List of Objects

Let's see an example that saves a list of students to a file and loads it back.

SaveStudents.java▶ Try it
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
 
public class SaveStudents {
    static class Student implements Serializable {
        String name;
        int marks;
 
        Student(String name, int marks) {
            this.name = name;
            this.marks = marks;
        }
 
        @Override
        public String toString() {
            return name + "(" + marks + ")";
        }
    }
 
    public static void main(String[] args)
            throws IOException, ClassNotFoundException {
        List<Student> students = new ArrayList<>(List.of(
            new Student("Navika", 91), new Student("Srihitha", 78)));
 
        try (ObjectOutputStream out = new ObjectOutputStream(
                new FileOutputStream("students.ser"))) {
            out.writeObject(students);
        }
 
        try (ObjectInputStream in = new ObjectInputStream(
                new FileInputStream("students.ser"))) {
            @SuppressWarnings("unchecked")
            List<Student> loaded = (List<Student>) in.readObject();
            System.out.println("Loaded: " + loaded);
            System.out.println("Same object? " + (loaded == students));
        }
    }
}
Output
Loaded: [Navika(91), Srihitha(78)]
Same object? false

Explanation: One writeObject call saved the whole ArrayList and both Student objects inside it. readObject rebuilt new objects with the same data, which is why loaded == students is false. readObject returns Object, so the result is cast back to the list type. ClassNotFoundException is declared because the class of a saved object might not be available when reading.

Example: A Class That Isn't Serializable

NotSerializable.java▶ Try it
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectOutputStream;
 
public class NotSerializable {
    static class Card {
        String owner = "Advitha";
    }
 
    public static void main(String[] args) throws IOException {
        try (ObjectOutputStream out =
                new ObjectOutputStream(new ByteArrayOutputStream())) {
            out.writeObject(new Card());
        } catch (NotSerializableException e) {
            System.out.println("Cannot save: " + e.getMessage());
        }
    }
}
Output
Cannot save: NotSerializable$Card

Explanation: Card doesn't implement Serializable, so writeObject throws NotSerializableException with the class name as its message.

Common Mistakes

Forgetting implements Serializable on a class used inside the saved object. Every object reachable from the saved one must be serializable.

Expecting readObject to return the original object. It returns a new copy.

Deserializing data from strangers. It's a known security risk.

Practice

  1. Easy: Save a HashMap<String, Integer> of marks to a file with writeObject, read it back and print it.
  2. Harder: Add a field of a non-serializable class to Student and observe the exception. Then fix it by making that class serializable too.

Quick check: Object streams

4 questions
1Which method writes an object to a stream?
2What must the object's class implement?
3Is the object returned by readObject the same one that was written?
4What happens when writing an object whose class isn't serializable?

Key Takeaways

Was this tutorial helpful?

Lesson 348 of 482