transient Keyword in Java – Excluding Fields from Serialization
The transient keyword marks a field that must not be serialized. When an object is written with Java serialization, transient fields are skipped, and when it is read back they receive their default values (null, 0 or false).
It is used for sensitive data such as passwords, for values that can be recomputed, and for fields whose types cannot be serialized, such as connections, threads and loggers. This tutorial shows each case with runnable examples.
1. A Quick Look at Serialization
Serialization converts an object into a stream of bytes so it can be saved to a file, cached or sent over a network; deserialization rebuilds the object. A class opts in by implementing java.io.Serializable, and by default every non-static, non-transient field is written. transient is how you leave a field out.
2. Basic Example
import java.io.*;
public class TransientDemo {
static class User implements Serializable {
private static final long serialVersionUID = 1L;
String username;
transient String password; // never written to the stream
transient int loginCount; // primitive: restored as 0
static String server = "eu-1"; // static: not part of the object at all
User(String username, String password, int loginCount) {
this.username = username; this.password = password; this.loginCount = loginCount;
}
public String toString() {
return "User[username=" + username + ", password=" + password + ", loginCount=" + loginCount + "]";
}
}
public static void main(String[] args) throws Exception {
User before = new User("asha", "s3cret!", 42);
System.out.println("Before: " + before);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(bytes)) {
out.writeObject(before);
}
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
User after = (User) in.readObject();
System.out.println("After: " + after);
}
}
}
Before: User[username=asha, password=s3cret!, loginCount=42] After: User[username=asha, password=null, loginCount=0]
usernamewas serialized and restored.passwordandloginCountwere skipped and came back asnulland0.staticfields belong to the class, not the object, so they are never serialized whether or not they are transient.
3. When to Use transient
| Situation | Example fields |
|---|---|
| Sensitive data that must not leave memory | Passwords, tokens, keys |
| Derived values that can be recomputed | Cached totals, areas, hash codes |
| Types that are not serializable | Thread, Socket, database connections, streams, loggers |
| Runtime-only state | Caches, locks, listeners |
4. Restoring transient Fields After Deserialization
Because transient fields come back with default values, restore them in a private readObject method, which the serialization mechanism calls automatically:
import java.io.*;
public class TransientRecompute {
static class Rectangle implements Serializable {
private static final long serialVersionUID = 1L;
private final double width, height;
private transient double area; // derived value: cheap to recompute
Rectangle(double width, double height) {
this.width = width; this.height = height;
this.area = width * height;
}
// Called during deserialization: restore the transient field
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
area = width * height;
}
public String toString() { return width + " x " + height + " = " + area; }
}
public static void main(String[] args) throws Exception {
Rectangle r = new Rectangle(4, 2.5);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(bytes)) { out.writeObject(r); }
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
System.out.println("Restored: " + in.readObject());
}
}
}
Restored: 4.0 x 2.5 = 10.0
Alternatively, initialise transient fields lazily on first use. Note that constructors and field initialisers of a Serializable class do not run during deserialization.
5. Avoiding NotSerializableException
If a serializable object holds a reference to a non-serializable object, serialization fails. Marking that field transient solves it:
import java.io.*;
import java.util.logging.Logger;
public class TransientNonSerializable {
static class Connection { /* not Serializable */ }
static class Session implements Serializable {
private static final long serialVersionUID = 1L;
String id = "S-1001";
transient Connection connection = new Connection(); // would cause NotSerializableException
transient Logger log = Logger.getLogger("session");
}
static class BadSession implements Serializable {
private static final long serialVersionUID = 1L;
String id = "S-1002";
Connection connection = new Connection(); // not transient!
}
static void save(Object o) {
try (ObjectOutputStream out = new ObjectOutputStream(new ByteArrayOutputStream())) {
out.writeObject(o);
System.out.println(o.getClass().getSimpleName() + ": serialized OK");
} catch (IOException e) {
System.out.println(o.getClass().getSimpleName() + ": " + e);
}
}
public static void main(String[] args) {
save(new Session());
save(new BadSession());
}
}
Session: serialized OK BadSession: java.io.NotSerializableException: TransientNonSerializable$Connection
6. Rules and Behaviour
transientapplies only to fields, not to methods, classes or local variables.- It has an effect only for classes using Java serialization (
Serializable). WithExternalizableyou write fields yourself, so the keyword is ignored. final transientfields cannot be reassigned inreadObject(without reflection), so they stay at their default value after deserialization. Avoid that combination.- Many JSON libraries respect
transienttoo: Gson skips transient fields by default, and Jackson can be configured to (MapperFeature.PROPAGATE_TRANSIENT_MARKER). - In JPA, the
@Transientannotation (not the keyword) excludes a field from database persistence.
7. transient vs static vs volatile
| Keyword | Purpose | Serialized? |
|---|---|---|
transient | Exclude an instance field from serialization | No |
static | Field belongs to the class, shared by all objects | No (not part of the object) |
volatile | Make writes visible across threads | Yes (unrelated to serialization) |
8. Summary
transientfields are skipped during serialization and get default values on deserialization.- Use it for secrets, derived data, runtime state and non-serializable references.
- Restore transient fields in
readObjector lazily on first use. - Static fields are never serialized; volatile is about threads, not serialization.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is the transient keyword in Java?
A field modifier that excludes the field from Java serialization. Its value is not written, and after deserialization it holds the type's default value.
Q2. What value does a transient field have after deserialization?
The default for its type: null for references, 0 for numbers and false for booleans, unless code such as readObject sets it.
Q3. Why are static fields not serialized?
Serialization saves the state of an object, and static fields belong to the class, not to any object.
Q4. Is it useful to mark a static field transient?
No. It compiles but has no effect, because static fields are never serialized anyway.
Q5. Can a method or class be transient?
No. transient applies only to fields.
Q6. Can a local variable be transient?
No. Local variables are not part of an object's state, so the modifier is not allowed on them.
Q7. What is the difference between transient and volatile?
transient excludes a field from serialization. volatile guarantees that writes to a field are visible to other threads. They solve unrelated problems.
Q8. How do I restore a transient field?
Define private void readObject(ObjectInputStream in), call in.defaultReadObject(), then recompute or reload the field. Lazy initialisation on first access also works.
Q9. Do constructors run during deserialization?
Not for the serializable class. Only the no-argument constructor of the first non-serializable superclass runs, so field initialisers in your class do not reset transient fields.
Q10. What happens with final transient fields?
They come back with their default value and cannot normally be reassigned in readObject, because they are final. Compile-time constants are an exception, as they are inlined.
Q11. Does transient work with Externalizable?
No. With Externalizable you explicitly write and read each field in writeExternal and readExternal, so the keyword has no effect.
Q12. Why mark a password field transient?
To keep it out of serialized bytes that might be stored on disk, cached or sent over the network, where it could be read by others.
Q13. How does transient prevent NotSerializableException?
Serialization fails when it reaches a field referencing a non-serializable object. Making that field transient tells serialization to skip it.
Q14. Do JSON libraries respect transient?
Gson skips transient fields by default. Jackson ignores the keyword by default but can be configured to honour it; it more commonly uses @JsonIgnore.
Q15. What is the difference between transient and @Transient in JPA?
The keyword excludes a field from Java serialization. JPA's @Transient annotation excludes a field from database persistence. A JPA entity field marked with the keyword is also not persisted.
Q16. Is transient inherited?
A field declared transient in a parent class stays transient when a subclass object is serialized, because the modifier belongs to the field's declaration.
Q17. Can I serialize a transient field manually?
Yes. In a private writeObject method you can write it in a custom form (for example encrypted) and read it back in readObject.
Q18. Does transient affect equals() or hashCode()?
No, it affects only serialization. If equals() uses a transient field, objects may compare differently after deserialization unless the field is restored.
Q19. Should derived values be transient?
Often yes. Values computed from other fields, such as cached totals, need not be stored; recomputing them reduces size and avoids inconsistent data.
Q20. Is Java serialization still recommended?
Use it with care. Deserializing untrusted data is a known security risk; many applications prefer JSON, Protocol Buffers or similar formats. The transient concept still applies to many of those libraries.