Course contents

The transient keyword in Java

How transient works with Java serialization: what is skipped, why you get defaults instead of initialisers, restoring state with readObject, final and static edge cases, serialVersionUID, Externalizable, Jackson and Gson behaviour, and serialization security.

PremiumGood to knowLesson13 min readCoreReviewed Oct 2026 · Java 21
On this page
  1. Picture it first: packing a suitcase for a move
  2. Under the hood: what serialization skips and what you get back
  3. Restoring transient state with readObject
  4. Real world: when to use transient (and what replaces it)
  5. Advanced: JSON libraries, records and security
  6. How to say it in the interview

🫥 What is the transient keyword?

transient marks an instance field that Java serialization must skip. When an object is written with ObjectOutputStream, its transient fields aren't written, and when it's read back, they come back as default values: null, 0 or false. For example, private transient String authToken; in a UserSession keeps a live token out of the bytes you put in a cache or a file, and the copy you deserialize has authToken == null.

It's a small keyword with a surprising number of interview follow-ups, because it sits on top of Java serialization, one of the most misunderstood (and most exploited) parts of the platform. Interviewers ask about it to check whether you know what serialization actually writes, why a field initialiser doesn't run on deserialize, how to rebuild skipped state, and whether you realise transient means nothing to Jackson unless you configure it.

What you’ll learn

  • Explain what Java serialization writes and why transient fields come back as null, 0 or false
  • Know why field initialisers and constructors don't run on deserialization, and which constructor does
  • Restore transient state and validate invariants in a private readObject after defaultReadObject()
  • Handle the edge cases: static fields, final transient, serialVersionUID and Externalizable
  • Predict how Jackson and Gson treat transient, including PROPAGATE_TRANSIENT_MARKER
  • Describe the security risk of deserializing untrusted data and the role of ObjectInputFilter

For this lesson, we'll focus on how Java serialization works at a high level, what transient skips and what you get back, the real use cases, transient combined with final and static, restoring state with readObject, serialVersionUID, Externalizable, how JSON libraries treat transient, and the security problems with Java serialization.

Below the line (out of scope)

  • Persistence annotations such as JPA's @Transient beyond a brief comparison
  • The serialization stream format byte by byte, and serialPersistentFields in depth
  • Deep copy via serialization: covered in Deep copy vs shallow copy

The 30-second answer

transient tells Java serialization to skip an instance field. On deserialization, the object is created without running its own constructor or field initialisers, so transient fields are left at their defaults: null, 0, false. Use it for secrets, caches, derived values and references to things that can't be serialized, like a Thread or a socket. If you need the value back, recompute it in a private readObject method after defaultReadObject(). static fields are never serialized anyway, and a final transient field stays at its default after deserialization unless you restore it by other means. Other serializers have their own rules: Gson skips transient fields by default, but Jackson only ignores the field itself, so a public getter still exposes it unless you enable PROPAGATE_TRANSIENT_MARKER or use @JsonIgnore.

Interview radar

Asked very often: What does transient skip, and what value does a transient field hold after deserialization? Senior rounds probe: Why don't field initialisers run on deserialization, and how do static, final transient and Externalizable change the picture? Production angle: A cached session object that deserializes with a null transient field after it moves between nodes, throwing NullPointerException on the first access.

01Picture it first: packing a suitcase for a move

Think of serialization as packing a suitcase for an object that's moving to another JVM, a file or a cache. You pack the things that define who the object is: its ID, its items, its settings. You don't pack the things that make no sense at the destination or are dangerous to carry: the key to your current flat (a session token), the milk in your fridge (a cache), or the house itself (an open database connection). transient is the "don't pack" sticker.

When the suitcase is unpacked, the unpacked slots aren't magically refilled. They're empty, and it's your job to restock them. The diagram below shows a session object going through that round trip.

Fig. 1

A UserSession object with fields userId, authToken, cache and failedAttempts passes through ObjectOutputStream; only userId is written to the byte stream, and after ObjectInputStream reads it back, authToken and cache are null and failedAttempts is 0

A UserSession object with fields userId, authToken, cache and failedAttempts passes through ObjectOutputStream; only userId is written to the byte stream, and after ObjectInputStream reads it back, authToken and cache are null and failedAttempts is 0

Notice three things:

  • Only non-transient, non-static instance fields go into the stream.
  • The deserialized copy gets type defaults, not the values from the field initialisers (= new HashMap<>(), = 3).
  • userId survives even though it's final: serialization writes and restores final fields that aren't transient.

02Under the hood: what serialization skips and what you get back

Try it yourself first

Before reading on: after this round trip, what are authToken, cache, failedAttempts, verified, lock and UserSession.region?

class UserSession implements Serializable {
    private static final long serialVersionUID = 1L;
    static String region = "ap-south-1";                  // static: never serialized

    private final String userId;
    private transient String authToken;                   // secret
    private transient Map<String, Object> cache = new HashMap<>();
    private transient int failedAttempts = 3;
    private transient boolean verified = true;
    private final transient Object lock = new Object();

    UserSession(String userId, String authToken) {
        this.userId = userId;
        this.authToken = authToken;
    }
}

var bytes = new ByteArrayOutputStream();
try (var out = new ObjectOutputStream(bytes)) {
    out.writeObject(new UserSession("u-42", "eyJhbGciOi..."));
}
UserSession.region = "eu-west-1";                         // change the static after writing

try (var in = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
    UserSession copy = (UserSession) in.readObject();
    // copy.userId          -> "u-42"
    // copy.authToken       -> null
    // copy.cache           -> null    (initialiser did not run)
    // copy.failedAttempts  -> 0       (not 3)
    // copy.verified        -> false   (not true)
    // copy.lock            -> null    (final, and still null)
    // UserSession.region   -> "eu-west-1" (whatever the class has now)
}

Here's why. When ObjectInputStream creates the object, it doesn't call UserSession's constructor. It allocates the object and runs only the no-arg constructor of the first non-serializable superclass, which here is Object(). Field initialisers are compiled into UserSession's constructors, so they don't run either. Then it fills the non-transient fields from the stream. Everything else keeps the default the JVM gave it at allocation time.

Notice three things:

  • cache is null, not empty. Code that calls cache.get(key) after deserialization throws NullPointerException. This is the most common real bug with transient.
  • static fields aren't part of any object's state, so the stream never contains them. You see the class's current value, whatever it is in the receiving JVM. Adding transient to a static field is legal and does nothing.
  • final transient is a trap. The field can't be assigned in readObject with a normal assignment (it's final, and you're not in a constructor), so it stays null. Options: drop final, restore it in readResolve by returning a freshly constructed object, or don't make it transient at all.

Those rules compose into one decision the runtime makes per field, shown below.

Fig. 2

A decision tree: if the class is Externalizable only what writeExternal writes is stored, otherwise a static field is never written, a transient field is skipped and returns a default, and any remaining field is written and restored including final fields

A decision tree: if the class is Externalizable only what writeExternal writes is stored, otherwise a static field is never written, a transient field is skipped and returns a default, and any remaining field is written and restored including final fields
Where candidates slip

Many candidates say "transient fields are reset to their initial values on deserialization". That's frequently a mistake, because initialisers don't run: you get the type's default (null, 0, false), not = new HashMap<>() or = 3. If the field matters after deserialization, restore it explicitly.

03Restoring transient state with readObject

The standard way to rebuild skipped fields is a private readObject method. The serialization machinery finds it reflectively (it must be exactly private void readObject(ObjectInputStream)), calls it instead of the default field restore, and you call defaultReadObject() first to read the normal fields.

Try it yourself first

Before reading on: a cart stores item prices and a cached total. How would you make the total correct after deserialization without writing it to the stream?

Premium lesson

Keep reading with the Java Pass

The rest of this lesson is part of Java One-Stop Interview Prep: in-depth explanations, diagrams, model answers and how to say them in the interview.

  • Real world: when to use transient (and what replaces it)
  • Advanced: JSON libraries, records and security
  • How to say it in the interview

From ₹199 · one-time payment · No auto-renewal

Practise this topicstatic, final & transient: interview questions & scenarios
Further reading (7)