๐ŸŽ“ A1Learner
๐Ÿ”
0 of 30 lessons completed

Java Serialization

Serialization turns an object into a stream of bytes. Deserialization rebuilds an object from those bytes.

A class that can travel

This Student class implements Serializable and carries a fixed version number. The main method prints the object before any travel.

import java.io.Serializable;

public class Main {
  public static void main(String[] args) {
    Student student = new Student("Mina Rao", 42, "secret123");
    System.out.println("Name: " + student.name);
    System.out.println("Id: " + student.id);
    System.out.println("Password: " + student.password);
  }
}

class Student implements Serializable {
  private static final long serialVersionUID = 1L;
  String name;
  int id;
  transient String password;

  Student(String name, int id, String password) {
    this.name = name;
    this.id = id;
    this.password = password;
  }
}

The version number stays fixed

ObjectStreamClass reads the version number from the class. The printed value matches the constant written in the source.

import java.io.ObjectStreamClass;
import java.io.Serializable;

public class Main {
  public static void main(String[] args) {
    long uid = ObjectStreamClass.lookup(Student.class).getSerialVersionUID();
    System.out.println("serialVersionUID: " + uid);
  }
}

class Student implements Serializable {
  private static final long serialVersionUID = 1L;
  String name;
  int id;
  transient String password;

  Student(String name, int id, String password) {
    this.name = name;
    this.id = id;
    this.password = password;
  }
}

Example

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Main {
  public static void main(String[] args) throws Exception {
    Student original = new Student("Mina Rao", 42, "secret123");
    try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.ser"))) {
      out.writeObject(original);
    }
    Student restored;
    try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.ser"))) {
      restored = (Student) in.readObject();
    }
    System.out.println("Name: " + restored.name);
    System.out.println("Id: " + restored.id);
    System.out.println("Password: " + restored.password);
  }
}

class Student implements Serializable {
  private static final long serialVersionUID = 1L;
  String name;
  int id;
  transient String password;

  Student(String name, int id, String password) {
    this.name = name;
    this.id = id;
    this.password = password;
  }
}

Key points

  • A class opts in by implementing the Serializable interface.
  • An explicit serialVersionUID gives the class a fixed version number.
  • A transient field is skipped during serialization.
  • An ObjectOutputStream writes objects to a stream.
  • An ObjectInputStream reads objects back from a stream.
  • Deserializing data from an untrusted source is a known attack surface.
  • New designs usually prefer text formats such as JSON over Java serialization.

In this example, one student is written to a relative file and read back in the same run, and the transient password prints null because it never travelled.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

Why does the restored student print a null password?