Course topics

By WebNest Studio Engineering Team

Java - Core Tutorial

transient Keyword in Java

When an object is serialized in Java — converted into a byte stream so it can be saved to a file, sent over a network, or stored elsewhere — the default behavior is to serialize every non-static field of that object, including all of its instance data, recursively. Most of the time that default is exactly what you want. Sometimes, though, a field genuinely should not be part of the saved representation, and that is what the transient keyword is for.

Marking a field transient tells the serialization mechanism to skip that field entirely: its value is simply not written into the byte stream, and when the object is later deserialized, that field comes back holding its type's plain default value rather than whatever it held before serialization.

Why it matters

Serialized objects are written to files, caches, session stores and message queues, where they can be read by anyone with access to that storage. A password or token left in a serialized object is a security problem. transient is the standard way to keep a field out of the saved form, and it is also what allows a class that holds a connection or a thread to be serialized at all.

Default Serialization Behavior (Without transient)

A class that implements java.io.Serializable has every one of its non-static fields written out by ObjectOutputStream when an instance is serialized, and read back by ObjectInputStream during deserialization. This works recursively — if a field is itself an object, that object must also be serializable (or also marked transient), or serialization fails at runtime with a NotSerializableException.

Why You Would Mark a Field transient

There are three common, legitimate reasons to exclude a field from serialization.

  • Sensitive data — a password, security token, or API key should never be written into a serialized byte stream that might end up on disk or in transit.
  • Derived or cacheable data — a field that can always be recomputed cheaply from other fields (like a cached hash code or a computed total) doesn't need to be persisted; it can simply be recalculated after deserialization.
  • Fields of a non-serializable type — a field holding a Thread, a Socket, a database connection, or any other resource tied to the live JVM process makes no sense to serialize (and often can't be, throwing NotSerializableException if you try); marking it transient lets the rest of the object serialize successfully.

What Happens to a transient Field After Deserialization

A transient field is not merely "skipped and left alone" — after deserialization, it is explicitly set to its type's default value: 0 (or 0.0) for numeric primitives, false for boolean, '\u0000' for char, and null for any reference type (including String). Any code that relies on a deserialized object must account for the fact that transient fields will need to be re-initialized manually, if they are needed at all after deserialization.

Example

Serializing an object with a transient password field, then inspecting it after deserialization

Java
import java.io.*;

class UserSession implements Serializable {
    String username;
    transient String password; // deliberately excluded from serialization

    UserSession(String username, String password) {
        this.username = username;
        this.password = password;
    }
}

public class TransientDemo {
    public static void main(String[] args) throws Exception {
        UserSession original = new UserSession("asha", "SuperSecret123");
        System.out.println("Before serialization -> username: " + original.username + ", password: " + original.password);

        // Serialize to a byte array (in-memory, no file needed for this demo)
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        try (ObjectOutputStream out = new ObjectOutputStream(byteStream)) {
            out.writeObject(original);
        }

        // Deserialize back into a new object
        ByteArrayInputStream inStream = new ByteArrayInputStream(byteStream.toByteArray());
        UserSession restored;
        try (ObjectInputStream in = new ObjectInputStream(inStream)) {
            restored = (UserSession) in.readObject();
        }

        System.out.println("After deserialization -> username: " + restored.username + ", password: " + restored.password);
    }
}
Output
Before serialization -> username: asha, password: SuperSecret123
After deserialization -> username: asha, password: null

Common Mistakes

  • Assuming a transient field keeps its original value after deserialization — it is reset to the type's default (0/false/null), not preserved.
  • Forgetting to mark a Thread, Socket, or other live-resource field transient, causing serialization to fail at runtime with NotSerializableException.
  • Marking a field transient and then relying on it being usable immediately after deserialization without re-initializing it manually.
  • Believing transient affects static fields — static fields are never serialized in the first place (serialization only applies to instance state), so marking one transient has no effect.

Exercise

As written, the program saves the PIN along with the owner's name and prints asha 4321. Change the Account class so the PIN is not serialized.

Expected output: asha 0

Java · starter code
import java.io.*;

class Account implements Serializable {
    String owner;
    int pin; // TODO: keep this field out of the serialized form

    Account(String owner, int pin) {
        this.owner = owner;
        this.pin = pin;
    }
}

public class TransientPin {
    public static void main(String[] args) throws Exception {
        Account original = new Account("asha", 4321);

        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        try (ObjectOutputStream out = new ObjectOutputStream(bytes)) {
            out.writeObject(original);
        }

        Account restored;
        try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
            restored = (Account) in.readObject();
        }

        System.out.println(restored.owner + " " + restored.pin);
    }
}
Show hints
  • Only the declaration of pin needs to change.
  • A transient int comes back as 0 after deserialization.
Show solution
Java · solution
import java.io.*;

class Account implements Serializable {
    String owner;
    transient int pin; // not written to the byte stream

    Account(String owner, int pin) {
        this.owner = owner;
        this.pin = pin;
    }
}

public class TransientPin {
    public static void main(String[] args) throws Exception {
        Account original = new Account("asha", 4321);

        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        try (ObjectOutputStream out = new ObjectOutputStream(bytes)) {
            out.writeObject(original);
        }

        Account restored;
        try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
            restored = (Account) in.readObject();
        }

        System.out.println(restored.owner + " " + restored.pin); // asha 0
    }
}

Quick quiz

1. What value does a transient String field have after the object is deserialized?

  • A. null
  • B. An empty string
  • C. Its original value
  • D. It throws an exception
Show answer

A. A transient field is not saved, so it comes back as the default for its type, which is null for a reference type.

2. A serializable class has a Thread field that is not marked transient. What happens when an instance holding a thread is serialized?

  • A. The thread is saved and restarted later
  • B. NotSerializableException is thrown
  • C. The field is skipped automatically
  • D. The code does not compile
Show answer

B. Thread does not implement Serializable, so writing the object fails at runtime.

3. What is the effect of marking a static field transient?

  • A. The field is serialized twice
  • B. The field becomes an instance field
  • C. The field is excluded from serialization, which it was already
  • D. It does not compile
Show answer

C. Static fields belong to the class and are never serialized, so transient adds nothing.

Interview questions

What is the transient keyword used for?

Show answer

It marks an instance field that should be left out when the object is serialized. Typical cases are sensitive values such as passwords, values that can be recalculated from other fields, and fields whose type cannot be serialized, such as a thread or a database connection. After deserialization the field holds the default value for its type.

What is the difference between transient and static with respect to serialization?

Show answer

Neither is written to the stream, but for different reasons. A static field is part of the class and not of any object, so serialization, which saves object state, does not include it; after deserialization it has whatever value the class currently holds. A transient field is part of the object and is excluded on purpose; after deserialization it has the default value for its type.

How can a transient field be given a value again after deserialization?

Show answer

Define a private void readObject(ObjectInputStream in) method in the class. Call in.defaultReadObject() first to restore the ordinary fields, then set the transient field, for example by recalculating it or opening a new connection. Another option is to initialise the field lazily the first time it is used.

Key Points to Remember

  • By default, serialization writes out every non-static field of an object, recursively.
  • transient explicitly excludes a field from serialization — typical uses are passwords, derived/cacheable data, and non-serializable resource types like Thread or Socket.
  • A transient field comes back as its type's default value (0, false, or null) after deserialization, not its original value.
  • Omitting transient on a non-serializable field type causes a NotSerializableException when serialization is attempted.

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering