In this article, we will discuss what happens to final data member when transient keyword or modifier applied during serialization process
This is one of the tricky questions asked in Java interview
Q) What happens in serialization process, if we declare final variable with transient keyword ?
- To answer this question, we need to revisit definition of both transient and final keywords
- So, let’s go through in detail
1. transient keyword:
- Transient keyword/modifier is applicable only for variables
- We can stop persisting specific variables, by declaring transient keyword
- During serialization, JVM ignores original value of transient variable and saves default value to file (i.e.; 0 for int data-type, null for String data-type)
- Examples: Customer SSN or password need not to be stored. Hence, it’s a good practice to declare those variables as transient
- So whenever we encounter transient keyword, it means that not to serialize
2. final variable:
- variable declared with final modifier is known as final variable
- value of final variable can’t be changed, once it‘s initialized
- final variables are CONSTANT
Very important: final variable can be initialized at 3 places either
- at the time of variable declaration i.e.; explicit initialization
- inside constructor, rather parameterized constructor
- instance initialization block
So when we declare any variable as both final & transient, then there are 2 cases,
Case 1: Initializing final transient variable at the time of declaration (explicit initialization)
- This case is very simple, as during serialization process directly value is serialized instead of final variable
- Important : There is no impact on final variable declaring as transient
- In the below example customerAge is declared as final as well as transient and explicitly initialized with value 10
Case 2 & 3: Initializing final transient variable inside constructor or instance block
Serialization :
These cases are bit tricky; when we serialize an Object
- all non-final instance variables will be serialized
- all non-final transient variable won’t be serialized
- all final non-transient variable will be serialized (directly as values)
- Important : But all final transient variable won’t be serialized
De-Serialization :
- During de-serialization process, constructor of an object isn’t invoked and this is handled by JVM for object instantiation
- after de-serialization process final transient variable will be assigned to default value
Demo example on Transient keyword with final variable:
- For objects to participate in serialization & de-serialization process, corresponding class should implement java.io.Serializable interface
- Otherwise, NotSerializableException will be thrown
Step 1: Create POJO which implements java.io.Serializable interface
In Customer POJO, there are 4 member variables with
- customerId declared as final (final variable)
- customerName declared as final transient keyword
- customerAge declared as final transient keyword (explicitly initialized)
- customerSSN declared with transient keyword (instance variable)
Customer.java
package in.bench.resources.serialization;
import java.io.Serializable;
public class Customer implements Serializable {
// member variables
final int customerId;
transient final String customerName;
transient final int customerAge = 10;
transient int customerSSN;
// 3-arg parameterized constructor
public Customer(int customerId, String customerName,
int customerSSN) {
this.customerId = customerId;
this.customerName = customerName; // final transient
this.customerSSN = customerSSN;
}
// overriding toString() method
@Override
public String toString() {
return "Customer ["
+ "customerId=" + customerId
+ ", customerName=" + customerName
+ ", customerAge=" + customerAge
+ ", customerSSN=" + customerSSN
+ "]";
}
}
Step 2: Main program to demonstrate serialization/de-serialization
- To Serialize any Object, we can use ObjectOutputStream & FileOutputStream to write/save to the file (in binary format)
- To De-Serialize any Object, we can use ObjectInputStream & FileInputStream to read/restore from file (which is in binary format) into Java heap memory
TransientWithFinalDemo.java
package in.bench.resources.serialization;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class TransientWithFinalDemo {
public static void main(String[] args) {
// create an customer instance using 3-arg constructor
Customer serializeCustomer =
new Customer(107, "Mike", 117896);
// creating output stream variables
FileOutputStream fos = null;
ObjectOutputStream oos = null;
// creating input stream variables
FileInputStream fis = null;
ObjectInputStream ois = null;
// creating customer object reference
// to hold values after de-serialization
Customer deSerializeCustomer = null;
try {
// for writing or saving binary data
fos = new FileOutputStream("Customer.ser");
// converting java-object to binary-format
oos = new ObjectOutputStream(fos);
// writing or saving customer object's value to stream
oos.writeObject(serializeCustomer);
oos.flush();
oos.close();
System.out.println("Serialization success: Customer"
+ " object saved to Customer.ser file\n");
// reading binary data
fis = new FileInputStream("Customer.ser");
// converting binary-data to java-object
ois = new ObjectInputStream(fis);
// reading object's value and casting to Customer class
deSerializeCustomer = (Customer) ois.readObject();
ois.close();
System.out.println("De-Serialization success: Customer"
+ " object de-serialized from Customer.ser file\n");
}
catch (FileNotFoundException fnfex) {
fnfex.printStackTrace();
}
catch (IOException ioex) {
ioex.printStackTrace();
}
catch (ClassNotFoundException ccex) {
ccex.printStackTrace();
}
// printing customer object to console using toString() method
System.out.println("Printing customer values from "
+ "de-serialized object... \n" + deSerializeCustomer);
}
}
Output:
Serialization success: Customer object saved to Customer.ser file
De-Serialization success: Customer object de-serialized
from Customer.ser file
Printing customer values from de-serialized object...
Customer [customerId=107, customerName=null, customerAge=10,
customerSSN=0]
Explanation:
During Serialization process, in above Customer POJO,
- final customerId variable will be serialized
- final transient customerName variable won’t be serialized
- explicitly initialized final transient customerAge variable will be serialized directly as value
- regular transient customerSSN instance variable won’t be serialized
During De-Serialization process,
- final customerId variable will be de-serialized and restored
- final transient customerName variable will be restored to default value, as it doesn’t get serialized (null for this case)
- explicitly initialized final transient customerAge variable will be restored correctly as it’s saved as value directly
- regular transient customerSSN instance variable will be restored to default value (0 for this case)
Conclusion:
- If final transient variable is initialized in any other way except explicitly initializing at the time of declaration, then value restored back during de-serialization is default value. Like 0 for integer, null for String, etc
- But explicit initialization of final transient variable will result in getting back original back for respective fields during de-serialization
- Whereas, final transient variable initialized by using instance block or constructor will assign default values for respective fields during de-serialization
Related Articles:
- Java – Serialization and De-Serialization Tutorial Index
- Java – Introduction to Serialization and De-Serialization
- Java – Serializable interface
- Java – Transient keyword with Serialization
- Java – Transient keyword with static variable in Serialization
- Java – Transient keyword with final variable in Serialization
- Java – Serializing a variable with transient modifier or keyword
- Java – Order of Serialization and De-Serialization
- Java – Serialization with Aggregation
- Java – Serialization with Inheritance
- Java – Externalization in detail
- Java – Serializable v/s Externalizable
- Java – Importance of SerialVersionUID in Serialization
- Java – Singleton Design pattern with Serialization
- Java – How to construct a singleton class in a multi-threaded environment ?
- Java – Singleton design pattern, restricting Object creation by overriding readResolve() method
- Java – How to stop Serialization ?
- Java – How to serialize and de-serialize ArrayList ?
- Java – Interview question & answers on Serialization and Externalization
References:
- https://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
- https://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html
- https://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html
- https://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html
- https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
- https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html
- http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.3
Happy Coding !!
Happy Learning !!