skip to content

What is the Serializable interface in Java, and what does implementing it actually do?

level: juniorimportance: must knowfreq 70%

answer

  1. Marker interface, no methods
  2. ObjectOutputStream/ObjectInputStream
  3. Whole object graph, recursive
  4. NotSerializableException at runtime
  5. serialVersionUID controls versioning

basics

~10 s

Serializable is an empty interface a class implements to say its objects can be turned into bytes and back. It has no methods; it just marks the class as allowed to be serialized.

solid answer

~40 s

Serializable is a marker interface (it declares no methods) in java.io. Implementing it tells the JVM that instances may be converted into a byte stream by ObjectOutputStream and reconstructed by ObjectInputStream. Serialization captures the object graph: the object's non-transient, non-static instance fields, recursively following references, so every referenced object must also be Serializable or you get a NotSerializableException at runtime. Because it's a marker, you write no code for default behavior; the JVM uses reflection. You should also declare a serialVersionUID so versioning is explicit. It is used to persist objects to disk, send them over a network (RMI), or cache them, though modern systems often prefer JSON/Protobuf for cross-platform safety.

code

java · 20 lines
java
import java.io.*;

class Point implements Serializable {
    private static final long serialVersionUID = 1L;
    int x, y;
    Point(int x, int y) { this.x = x; this.y = y; }
}

public class Demo {
    public static void main(String[] args) throws Exception {
        Point p = new Point(3, 4);
        try (var out = new ObjectOutputStream(new FileOutputStream("p.ser"))) {
            out.writeObject(p);            // serialize
        }
        try (var in = new ObjectInputStream(new FileInputStream("p.ser"))) {
            Point q = (Point) in.readObject(); // deserialize
            System.out.println(q.x + "," + q.y); // 3,4
        }
    }
}

go deeper

for a junior

Knows Serializable is an empty marker interface, that you add 'implements Serializable', and that ObjectOutputStream/ObjectInputStream do the work.

for a middle

Explains the object-graph recursion, NotSerializableException, the role of serialVersionUID, and that transient/static fields are excluded.

for a senior

Discusses versioning compatibility, when to prefer JSON/Protobuf, security risks of deserializing untrusted input, and that the constructor is bypassed.

for a principal

Frames serialization in system design: format choice for evolution and interop, deserialization attack surface and mitigations (allowlists, ObjectInputFilter), and why Java serialization is largely discouraged for new external boundaries.

## What serialization is **Serialization** is converting an in-memory Java object into a flat sequence of **bytes** so it can be stored (file, DB) or transmitted (network) and later **deserialized** — reconstructed into an equivalent object. Think of flattening a structure into a ribbon you can mail, then unfolding it on the other side. ## The Serializable interface `java.io.Serializable` is a **marker interface**: an interface with **no methods and no fields**. A marker interface exists only to *tag* a class with metadata the runtime checks. By writing `class Foo implements Serializable`, you assert "instances of Foo may be serialized." You add **no code** — the JVM provides the default behavior automatically. ## How the default mechanism works You serialize with **`ObjectOutputStream`** and its `writeObject(obj)` method, and read back with **`ObjectInputStream`** and `readObject()`. Under the hood the JVM uses **reflection** to walk the object's fields: - It writes the class descriptor (class name, `serialVersionUID`, field metadata). - It writes each **instance field** that is **not `transient`** and **not `static`**. - For each field that is itself an object reference, it recursively serializes that object too. This is the **object graph**: a tree/graph of all reachable objects. Shared references and cycles are handled by a back-reference table, so the same object isn't written twice and cycles don't loop forever. ## Why every referenced object must be Serializable If the graph reaches an object whose class does **not** implement `Serializable`, serialization fails at runtime with **`java.io.NotSerializableException`**, naming the offending class. There is no compile-time check — `Serializable` has no methods to force, so the requirement is verified only when you actually serialize. ## serialVersionUID Each serializable class has a `serialVersionUID` — a long that identifies the class version. If you don't declare one, the compiler generates it from the class structure; any structural change produces a different value, and deserializing old bytes throws `InvalidClassException`. Best practice: declare `private static final long serialVersionUID = 1L;` explicitly so you control compatibility. ## What it does NOT serialize Default serialization skips **`transient`** fields and **`static`** fields (statics belong to the class, not the instance). Constructors are **not** run on deserialization — the object is rebuilt directly from bytes via reflection. ## When to use / avoid Use it for quick JVM-to-JVM persistence, caching, or legacy RMI. Avoid it for untrusted input (deserializing attacker-controlled bytes is a major security risk — gadget-chain RCE) and for cross-language or long-term formats, where JSON, Protobuf, or Avro are safer and more portable.

  • What happens if a serializable class references an object whose class is not Serializable?
    Serialization throws java.io.NotSerializableException at runtime, naming that class. There's no compile-time check because Serializable has no methods. Fix it by making the referenced class Serializable or marking that field transient.
  • Does deserialization call the constructor?
    No. The object is reconstructed via reflection from the byte stream; no constructor of the serializable class runs. (The no-arg constructor of the first non-serializable superclass IS invoked, however.)

Serializable is like a 'this parcel may be shipped' sticker — it carries no instructions, it just authorizes the postal system (the JVM) to flatten and box the contents.

saying these in an interview costs you the question

  • Thinking Serializable has methods you must implement
  • Believing it does a compile-time check that the whole graph is serializable
  • Assuming static fields are saved
  • Thinking the constructor runs on deserialization
  • Ignoring serialVersionUID and being surprised by InvalidClassException

context