0Pricing
Java Academy · Lesson

Custom Serialization: writeObject and readObject

Override writeObject and readObject for encryption, compression, or custom field handling.

Custom Serialization: writeObject and readObject is a free Java Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

When Default Serialization Is Not Enough

Default serialization saves all non-transient fields as-is. Sometimes you need encryption, compression, or a different representation. That's where writeObject / readObject hooks come in.

Declaring writeObject

Add a private void writeObject(ObjectOutputStream oos) method. Java calls it instead of the default mechanism. You control exactly what gets written.

private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.defaultWriteObject(); // write non-transient fields normally
    oos.writeUTF(encrypt(this.secret)); // write encrypted secret
}

Declaring readObject

Add a private void readObject(ObjectInputStream ois) method. Java calls it during deserialization. You read in the exact same order you wrote.

private void readObject(ObjectInputStream ois)
        throws IOException, ClassNotFoundException {
    ois.defaultReadObject(); // restore non-transient fields
    this.secret = decrypt(ois.readUTF()); // decrypt and restore
}

Order Matters

Whatever you write in writeObject must be read back in the same order in readObject. Mismatched order causes StreamCorruptedException.

private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.writeInt(version);
    oos.writeUTF(data);
}
private void readObject(ObjectInputStream ois)
        throws IOException, ClassNotFoundException {
    this.version = ois.readInt();  // same order
    this.data    = ois.readUTF();
}

Compressing Data During Serialization

Wrap the stream with GZIPOutputStream inside writeObject to compress large fields, then GZIPInputStream inside readObject to decompress.

private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.defaultWriteObject();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try (GZIPOutputStream gz = new GZIPOutputStream(bos)) {
        gz.write(largePayload.getBytes());
    }
    oos.writeObject(bos.toByteArray());
}

The readResolve Hook

readResolve() is called after deserialization. Return a replacement object — useful for singletons and enums to ensure only one instance exists after deserialization.

public class AppConfig implements Serializable {
    private static final AppConfig INSTANCE = new AppConfig();
    private AppConfig() {}
    public static AppConfig getInstance() { return INSTANCE; }
    private Object readResolve() { return INSTANCE; } // return singleton
}

The writeReplace Hook

writeReplace() is called before serialization. Return a different object to be serialized instead — useful for proxy patterns and serialization surrogates.

private Object writeReplace() {
    return new UserProxy(this.id); // serialize a lightweight proxy
}

Validating Fields in readObject

You can add validation logic inside readObject to reject invalid or tampered data as part of a defense-in-depth strategy.

private void readObject(ObjectInputStream ois)
        throws IOException, ClassNotFoundException {
    ois.defaultReadObject();
    if (age < 0 || age > 150) {
        throw new InvalidObjectException("Invalid age: " + age);
    }
}

Handling Version Changes

Use a version field in writeObject so that readObject can handle both old and new formats gracefully during migrations.

private static final int SERIAL_VERSION = 2;
private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.defaultWriteObject();
    oos.writeInt(SERIAL_VERSION);
    if (SERIAL_VERSION >= 2) oos.writeUTF(email); // new field
}
private void readObject(ObjectInputStream ois)
        throws IOException, ClassNotFoundException {
    ois.defaultReadObject();
    int v = ois.readInt();
    if (v >= 2) this.email = ois.readUTF();
}

Serialization Proxy Pattern

A robust approach: write a private static inner class that captures the minimum state, then use writeReplace to write the proxy and its readResolve to reconstruct the original.

Performance Considerations

Custom serialization adds method-call overhead but can reduce payload size significantly. Benchmark before optimizing; use Externalizable for maximum control.

Quick Check

What must be true about the order in writeObject and readObject?

Recap

Override writeObject / readObject for encryption, compression, or custom formats. Use readResolve for singletons. Always read in the same order as you write.

Frequently asked questions

Is the “Custom Serialization: writeObject and readObject” lesson free?

Yes — the full text of “Custom Serialization: writeObject and readObject” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.

What will I learn in “Custom Serialization: writeObject and readObject”?

Override writeObject and readObject for encryption, compression, or custom field handling. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Java Academy?

No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Custom Serialization: writeObject and readObject” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Java Academy lesson?

Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Java Serialization Basics
  2. transient Fields and serialVersionUID
  3. Custom Serialization: writeObject and readObject
  4. Modern Alternatives: JSON and Protocol Buffers
← Back to Java Academy