Transient Keyword in Java

Naveen AnamaneniUpdated · 4 min read

The transient keyword in Java is a field modifier that tells serialization to skip that field. When an object is serialized, a transient field isn't written; when it's deserialized, the field gets its default value: null for objects, 0 for numbers and false for boolean. It is used for data that shouldn't be saved, such as passwords, or can't be saved, such as open connections, and for values that can easily be recalculated. In this lesson, you will learn how to use transient and how to restore skipped fields.

Syntax

Syntax
private transient String password;
private transient int cachedTotal;

When to Use transient

ReasonExample field
Sensitive dataA password or security token
Not serializableA Thread, socket, open stream or database connection
Can be recalculatedA cached total, a formatted string
Only meaningful nowA "last viewed" timestamp for the current session

Example: Skipping a Password and a Cache

Let's see an example where two fields are transient.

TransientDemo.java▶ Try it
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serial;
import java.io.Serializable;
 
public class TransientDemo {
    static class Account implements Serializable {
        @Serial
        private static final long serialVersionUID = 1L;
 
        String user;
        transient String password;
        int[] marks;
        transient int cachedTotal;
 
        Account(String user, String password, int... marks) {
            this.user = user;
            this.password = password;
            this.marks = marks;
            for (int m : marks) {
                cachedTotal += m;
            }
        }
    }
 
    public static void main(String[] args)
            throws IOException, ClassNotFoundException {
        Account a = new Account("Srihitha", "s3cret", 78, 85);
        System.out.println("Before: " + a.user + ", " + a.password
            + ", total " + a.cachedTotal);
 
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        try (ObjectOutputStream out = new ObjectOutputStream(bytes)) {
            out.writeObject(a);
        }
        try (ObjectInputStream in = new ObjectInputStream(
                new ByteArrayInputStream(bytes.toByteArray()))) {
            Account b = (Account) in.readObject();
            System.out.println("After:  " + b.user + ", " + b.password
                + ", total " + b.cachedTotal);
        }
    }
}
Output
Before: Srihitha, s3cret, total 163
After:  Srihitha, null, total 0

Explanation: user and marks were saved and restored. The transient fields were skipped: password came back as null and cachedTotal as 0, their default values. The password never appeared in the serialized bytes.

Restoring a transient Field

A class can recompute transient fields after deserialization by adding a private readObject method:

Recompute.java▶ Try it
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serial;
import java.io.Serializable;
import java.util.Arrays;
 
public class Recompute {
    static class Report implements Serializable {
        @Serial
        private static final long serialVersionUID = 1L;
        int[] marks = {91, 85};
        transient int total = Arrays.stream(marks).sum();
 
        @Serial
        private void readObject(ObjectInputStream in)
                throws IOException, ClassNotFoundException {
            in.defaultReadObject();
            total = Arrays.stream(marks).sum();
        }
    }
 
    public static void main(String[] args)
            throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        try (ObjectOutputStream out = new ObjectOutputStream(bytes)) {
            out.writeObject(new Report());
        }
        try (ObjectInputStream in = new ObjectInputStream(
                new ByteArrayInputStream(bytes.toByteArray()))) {
            System.out.println("Total: " + ((Report) in.readObject()).total);
        }
    }
}
Output
Total: 176

Explanation: Java calls the private readObject method during deserialization. defaultReadObject() restores the normal fields, then the method recalculates total from the restored marks. Field initializers such as = Arrays.stream(marks).sum() don't run during deserialization, which is why this method is needed.

Common Mistakes

Expecting a field initializer to give a transient field its value back. Initializers and constructors don't run; use readObject.

Marking a needed field transient by accident. Its value is silently lost.

Thinking transient hides data from other formats like JSON. Libraries such as Jackson have their own rules.

Interview Corner

What is the transient keyword used for?

transient marks an instance field to be excluded from Java serialization. Its value isn't written to the stream, and after deserialization the field holds the default value for its type. It's used for sensitive data such as passwords, fields whose types aren't serializable, such as threads or connections, and derived values that can be recomputed, typically in a private readObject method.

Practice

  1. Easy: Make a User class with a transient loginTime field, serialize it, and show that the field is null afterwards.
  2. Harder: Add a transient DateTimeFormatter-based display string to a class and rebuild it in readObject.

Quick check: transient

4 questions
1What does transient do?
2What value does a transient int have after deserialization?
3Which field is a good candidate for transient?
4How can a transient field be rebuilt after loading?

Key Takeaways

Was this tutorial helpful?

Lesson 372 of 482