Definition
The problem and fixes:
- Problem:
Accountimplements Serializable but has a field of typeLogger(not Serializable). Serialization throwsNotSerializableException. - Fix 1:
transient Logger log;– skipped during serialization. - Fix 2: Make Logger implement Serializable (not always possible for JDK classes).
- Fix 3: Implement
writeObject/readObjectto manually serialize only the parts you need.
Trying to photocopy a bank file that contains a physical key (non-serializable object). The photocopier jams. Fix: remove the key before copying (transient), or use a digital photo of the key (custom serialization).
Understanding the Concepts
The problem
public class TransferService implements Serializable {
private String name;
private Logger log = Logger.getLogger("TransferService"); // NOT Serializable!
}
// ObjectOutputStream.writeObject(service) → NotSerializableException: Logger
Fix 1: transient
private transient Logger log = Logger.getLogger("TransferService");
// Skipped during serialization. On deserialization, log is null.
// Reinitialize in readObject:
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
this.log = Logger.getLogger("TransferService"); // reinitialize
}
Fix 2: make it Serializable (when possible)
// If you control the class:
public class MyHelper implements Serializable { ... }
What should a senior engineer know?
- All fields in the object graph must be Serializable (or transient). This includes nested objects.
- Jackson @JsonIgnore is the JSON equivalent – marks a field as not included in JSON output.
What are common mistakes?
A common mistake is forgetting to declare serialVersionUID, which causes deserialization failures when the class changes.
Wrong approach:
package com.bank.model;
import java.io.Serializable;
// WRONG: no serialVersionUID
public class Account implements Serializable {
private String accountId;
private java.math.BigDecimal balance;
}
// If you add a field later, old serialized data cannot be read
Correct approach:
package com.bank.model;
import java.io.Serializable;
import java.math.BigDecimal;
// CORRECT: explicit serialVersionUID
public class Account implements Serializable {
private static final long serialVersionUID = 1L;
private String accountId;
private BigDecimal balance;
}
// Adding new fields with defaults still allows reading old data
Another mistake is serializing sensitive fields like passwords or PINs. Always mark them transient to exclude them from the byte stream.
What are the edge cases?
Edge cases can cause unexpected behavior in banking applications. Here are some to watch for.
package com.bank.edge;
public class EdgeCaseDemo {
public static void main(String[] args) {
// Edge case 1: null handling
String accountId = null;
try {
System.out.println(accountId.length());
} catch (NullPointerException e) {
System.out.println("Null account ID");
}
// Edge case 2: empty vs null
String emptyId = "";
System.out.println(emptyId.isEmpty()); // true
System.out.println(emptyId == null); // false
// Edge case 3: boundary values
java.math.BigDecimal zero = java.math.BigDecimal.ZERO;
java.math.BigDecimal negativeBalance = new java.math.BigDecimal("-0.01");
System.out.println(zero.compareTo(negativeBalance) > 0); // true
}
}
Null account ID
true
false
true
Always test with null values, empty strings, boundary values, and negative amounts in banking applications.
What are common interview follow-up questions?
Interviewers often follow up with these related questions:
- How does this concept apply to a high-throughput banking transaction system?
- What are the performance implications in a production environment?
- How would you debug issues related to this concept?
- What tools would you use to monitor this in production?
- How does this behave differently in Java 8 vs Java 17+?
When answering follow-up questions, always relate your answer back to practical experience. For example, at National Bank of India, Rajesh debugged a production issue related to this concept by using JFR recordings and heap dumps. Providing concrete examples from banking systems shows the interviewer that you understand both the theory and the practice.
Visual Overview
Account implements Serializable
├── accountId: String (Serializable) → OK
├── balance: BigDecimal (Serializable) → OK
└── log: Logger (NOT Serializable) → NotSerializableException!
Fix: transient Logger log; → skipped, reinitialize in readObject()
Key Takeaway
A non-serializable, non-transient field causes NotSerializableException. Mark it transient and reinitialize in readObject(), or make the field's class Serializable.
One sentence to remember: every non-transient field must be Serializable, or serialization throws NotSerializableException.
---