transient Keyword and transient Variable in Java

transient is a variables modifier used in serialization. At the time of serialization, if we don’t want to save value of a particular variable in a file, then we use transient keyword. When JVM comes across transient keyword, it ignores original value of the variable and save default value of that variable data type. transient keyword plays an important role to meet security constraints. There are various real-life examples where we don’t want to save private data in file. Another use of transient keyword is not to serialize the variable whose value can be calculated/derived using other serialized objects or system such as age of a person, current date, etc. Practically we serialized only those fields which represent a state of instance, after all serialization is all about to save state of an object to a file. It is good habit to use transient keyword with private confidential fields of a class during serialization.

Or simply we can say that, In Java, the "transient" keyword is used to indicate that a variable should not be serialized when an object is being converted into a stream of bytes. When an object is serialized, all of its member variables are written to a stream of bytes, which can then be stored on disk or transmitted over a network. However, there are some variables that should not be included in the serialization process, and this is where the "transient" keyword comes in.

When a variable is declared as "transient", it is not included in the serialization process. This can be useful for variables that contain sensitive data, such as passwords or private keys, which should not be stored in a serialized form. It can also be useful for variables that do not need to be persisted, such as temporary variables that are used for calculations or other purposes.

Here is an example of how the "transient" keyword can be used in Java:In Java, the "transient" keyword is used to indicate that a variable should not be serialized when an object is being converted into a stream of bytes. When an object is serialized, all of its member variables are written to a stream of bytes, which can then be stored on disk or transmitted over a network. However, there are some variables that should not be included in the serialization process, and this is where the "transient" keyword comes in.

When a variable is declared as "transient", it is not included in the serialization process. This can be useful for variables that contain sensitive data, such as passwords or private keys, which should not be stored in a serialized form. It can also be useful for variables that do not need to be persisted, such as temporary variables that are used for calculations or other purposes.

  • Syntax:
private transient <mamber variable>;
or
transient private <member variable>;

Here is an example of how the "transient" keyword can be used in Java:

public class MyClass implements Serializable {
    private String name;
    private transient String password;
 
    // Constructor and methods omitted for brevity
 
    public String getPassword() {
        return password;
    }
}


In this example, the "name" variable will be included in the serialization process, but the "password" variable will not, since it has been declared as "transient". This means that when an object of this class is serialized, the password will not be included in the resulting stream of bytes.

It's worth noting that the "transient" keyword only affects the serialization process; it does not affect the behavior of the variable within the program itself. So, even though the "password" variable is not serialized, it can still be accessed and used within the program by calling the "getPassword()" method.
Let's take an another example, we have declared a class as Student, it has three data members id, name and age. If you serialize the object, all the values will be serialized but we don't want to serialize one value, e.g. age then we can declare the age data member as transient.

In this example, we have created two classes Student and PersistExample. The age data member of the Student class is declared as transient, its value will not be serialized.

If you deserialize the object, you will get the default value for transient variable.

Let's create a class with transient variable.

PersistExample.java
import java.io.*;      
public class Student implements Serializable{    
 int id;    
 String name;    
 transient int age;//Now it will not be serialized    
 public Student(int id, String name,int age) {    
  this.id = id;    
  this.name = name;    
  this.age=age;    
 }    
}    
class PersistExample{    
 public static void main(String args[])throws Exception{    
  Student s1 =new Student(292,"deepak",92);//creating object    
  //writing object into file    
  FileOutputStream f=new FileOutputStream("f.txt");    
  ObjectOutputStream out=new ObjectOutputStream(f);    
  out.writeObject(s1);    
  out.flush();    
  out.close();    
  f.close();    
  System.out.println("success");    
 }    
}
/*Output
 success
 */

DePersistExample.java
import java.io.*;    
class DePersist{    
 public static void main(String args[])throws Exception{    
  ObjectInputStream in=new ObjectInputStream(new FileInputStream("f.txt"));    
  Student s=(Student)in.readObject();    
  System.out.println(s.id+" "+s.name+" "+s.age);    
  in.close();    
 }    
}    
/*Output:
 292 deepak 0
 */

As you can see, printing age of the student returns 0 because value of age was not serialized.

Transient Variable in Java

Java transient variables are variables whose values are not serialized during serialization and that are initialized by default during de-serialization. For example, for an object transient variable, this behaviour can be customized using a Custom Serialized form or through a custom Externalizable interface. With a transient variable, you can prevent any object from being serialized. The transient keyword can be used to make any variable transient. If a property is marked as transient, it must have a default value during deserialization. De-serialized objects cannot be used otherwise.

Or simply, In Java, the transient keyword is used to mark a variable as transient. When applied to a variable, it instructs the Java Virtual Machine (JVM) to exclude the variable from the default serialization process. Serialization is the process of converting an object into a stream of bytes to store it in memory or transmit it over a network.

The main purpose of marking a variable as transient is to prevent its value from being persisted. This is particularly useful when dealing with sensitive or non-serializable data that should not be stored or transmitted. By excluding such variables from serialization, we can ensure the privacy and integrity of the data.

The following complete code example illustrates how to use transient variables in Java.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

    /**
     *
     * Java program demonstrating the transient nature of variables in Java, as well as the fact that their values can change
     */
    public class Main {
        public static void main(String args[]) {

            Book muthu = new Book(1026, "muthu", " not known", 3);
            System.out.println("Before Serialization: " + muthu);

            try {
                FileOutputStream fos = new FileOutputStream("muthu.ser");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(muthu);

                System.out.println("The book has been successfully Serialized ");

                FileInputStream fis = new FileInputStream("muthu.ser");
                ObjectInputStream ois = new ObjectInputStream(fis);
                Book oldmuthu = (Book) ois.readObject();

                System.out.println("The book has been successfully created from the serialized data");
                System.out.println("The books after seriazliation : " + oldmuthu);

            } catch (Exception e) {
                e.printStackTrace();
            }

        }


    }

    /*
     * Implementations of Serializable and transient variables.
     */
    class Book implements Serializable {
        private int ISBN;
        private String title;
        private String author;
        private transient int edition = 1; //transient variable not serialized

        public Book(int ISBN, String title, String author, int edition) {
            this.ISBN = ISBN;
            this.title = title;
            this.author = author;
            this.edition = edition;
        }

        @Override
        public String toString() {
            return "Book{" + "ISBN=" + ISBN + ", title=" + title + ", author=" + author + ", edition=" + edition + '}';
        }
    }


The following example illustrates serializing objects in Java. You will notice that transient variables are not serialized and stored, but are initialized with their default values, which is zero for the integer variable.

Due to the absence of the constructor during de-serialization, it will not receive the value that was passed in during the constructor. As a result, transient variables need to be handled carefully


Note: Both the transient keyword and transient variable are crucial components in managing the serialization process, providing control over what data is serialized and enhancing security in certain scenarios.
  • transient keyword suggests that the object should not be serialized, nor persisted. You can use it if you don't want to serialize heavy objects (such as Wrappers, for example, which can contain a lot of business logic).
  • @Transient annotation suggests that the object should not be persisted (if you've been playing with Hibernate, for example), but it can be serialized.
  • I've included the annotation explanation, because I remember being confused by the two. :-)
  • transient is used to specify which properties of an object will not be saved or serialised. For example, when saving an object to a file, transient specifies which properties or attributes will not be saved to that file when that object is saved to a file.
  • When the object is re-created from the file, the value of that transient attribute (or private property) will not be re-created as it was never saved, or serialised to that file. In some cases, you may want to avoid persisting some of these private instance variables or attributes of an object, transient allows you to do that.

When to use the transient keyword?
  • The transient modifier can be used where there are data members derived from the other data members within the same instance of the class.
  • This transient keyword can be used with the data members which do not depict the state of the object.
  • The data members of a non-serialized object or class can use a transient modifier.
  • The transient keyword in Java serves as a variable modifier in the context of serialization, allowing developers to exclude specific variables from being saved during the serialization process.
  • Serialization is the process of converting an object's state into a format that can be stored or transmitted, typically as a file or stream, and the Serializable interface is used for achieving serialization in Java.
  • Transient variables marked with the transient keyword are not saved in the serialized form of the object, making it useful for excluding sensitive or redundant data from serialized files.
  • The volatile keyword, on the other hand, ensures thread safety by providing memory visibility and preventing certain optimizations in multithreaded environments.
  • It is important to understand the distinction between transient and volatile keywords, as they serve different purposes: transient for serialization exclusion and volatile for thread safety.
  • Transient keywords can only be used for fields and member variables. Applying them to methods or local variables will result in a compilation error.
  • The Java compiler does not complain when you declare a variable both static and transient at the same time, but doing that makes no sense since transients are used to instruct the compiler not to save the variable, whereas static variables are not saved in the serialization process.
  • Using the transient and final keywords together, you can build a variable compiler that will not complain, but you will have to reinitialize a final variable when you deserialize.
  • Java transient variables are not saved or persistent when objects are serialized.
  • First and very logical case would be where you may have fields that are derived/calculated from other fields within instance of class. They should be calculated programmatically everytime rather than having the state be persisted via serialization. An example could be time-stamp based value; such as age of a person OR duration between a timestamp and current timestamp. In both cases, you would be calculating value of variable based on current system time rather than when the instance was serialized.
  • Second logical example can be any secure information which should not leak outside the JVM in any form (either in database OR byte stream).
  • Another example could be fields which are not marked as “Serializable” inside JDK or application code. Classes which do not implement Serializable interface and are referenced within any serializable class, cannot be serialized; and will throw “java.io.NotSerializableException” exception. These non-serializable references should be marked “transient” before serializing the main class.
  • And lastly, there are times when it simply doesn’t make sense to serialize some fields. Period. For example, In any class if you have added a logger reference, then what’s use of serializing that logger instance. Absolutely no use. You serialize the information which represent the state of instance, logically. Loggers never share the state of an instance. They are just utilities for programming/debugging purpose. Similar example can be reference of a Thread class. Threads represent a state of a process at any given point of time, and there is no use to store thread state with your instance; simply because they do not constitute the state of your class’s instance.

transient and static

Since static fields are not part of state of the object, there is no use/impact of using transient keyword with static variables. However there is no compilation error. transient and final : final variables are directly serialized by their values, so there is no use/impact of declaring final variable as transient. There is no compile-time error though.

// Java program to demonstrate transient keyword
// Filename Test.java
import java.io.*;
class Test implements Serializable
{
    // Normal variables
    int i = 10, j = 20;
 
    // Transient variables
    transient int k = 30;
 
    // Use of transient has no impact here
    transient static int l = 40;
    transient final int m = 50;
 
    public static void main(String[] args) throws Exception
    {
        Test input = new Test();
 
        // serialization
        FileOutputStream fos = new FileOutputStream("abc.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(input);
 
        // de-serialization
        FileInputStream fis = new FileInputStream("abc.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Test output = (Test)ois.readObject();
        System.out.println("i = " + output.i);
        System.out.println("j = " + output.j);
        System.out.println("k = " + output.k);
        System.out.println("l = " + output.l);  
        System.out.println("m = " + output.m);
    }
}

Output :
i = 10
j = 20
k = 0
l = 40
m = 50


Case study : How does a HashMap use transient keyword?

So far, we have been talking about concepts related to “transient” keyword which are mostly theoretical in nature. Let’s understand the proper use of “transient” which is used inside HashMap class very logically. It will give you better idea about real life usage of transient keyword in java.

HashMap is used to store key-value pairs, we all know that. And we also know that location of keys inside HashMap is calculated based on hash code obtained for instance of key. Now when we serialize a HashMap that means all keys inside HashMap and all values respective to key’s will also be serialized. After serialization, when we de-serialize the HashMap instance then all key instances will also be deserialized. We know that during this serialization/deserialization process, there may be loss of information (used to calculate hashcode) as well as most important is it is a NEW INSTANCE itself.

In java, any two instances (even of same class) can not have same hashcode. This is a big problem because the location where keys should be placed according to new hashcodes, are not in there correct positions. When retrieving the value of a key, you will be referring to the wrong index in this new HashMap.


So, when a hash map is serialized, it means that the hash index, and hence the ordering of the table is no longer valid and should not be preserved. This is the problem statement.

Now look at how it is solved inside HashMap class. If go through the sourcecode of HashMap.java, you will find below declarations:

transient Entry table[];
transient int size;
transient int modCount;
transient int hashSeed;
private transient Set entrySet;

All important fields have been marked at “transient” (all of them are actually calculated/change at runtime), so they are not part of serialized HashMap instance. To populate again this important information back, HashMap class uses writeObject() and readObject() methods as below:

private void writeObject(ObjectOutputStream objectoutputstream) throws IOException
{
  objectoutputstream.defaultWriteObject();
 
  if (table == EMPTY_TABLE)
    objectoutputstream.writeInt(roundUpToPowerOf2(threshold));
  else
    objectoutputstream.writeInt(table.length);
 
  objectoutputstream.writeInt(size);
 
  if (size > 0)
  {
    Map.Entry entry;
    for (Iterator iterator = entrySet0().iterator(); iterator.hasNext(); objectoutputstream.writeObject(entry.getValue()))
    {
      entry = (Map.Entry) iterator.next();
      objectoutputstream.writeObject(entry.getKey());
    }
  }
}
 
private void readObject(ObjectInputStream objectinputstream) throws IOException, ClassNotFoundException
{
  objectinputstream.defaultReadObject();
 
  if (loadFactor <= 0.0F || Float.isNaN(loadFactor))
    throw new InvalidObjectException((new StringBuilder())
    .append("Illegal load factor: ").append(loadFactor).toString());
 
  table = (Entry[]) EMPTY_TABLE;
  objectinputstream.readInt();
 
  int i = objectinputstream.readInt();
  if (i < 0)
    throw new InvalidObjectException((new StringBuilder()).append("Illegal mappings count: ").append(i).toString());
  int j = (int) Math.min((float) i * Math.min(1.0F / loadFactor, 4F), 1.073742E+009F);
  if (i > 0)
    inflateTable(j);
  else
    threshold = j;
 
  init();
 
  for (int k = 0; k < i; k++)
  {
    Object obj = objectinputstream.readObject();
    Object obj1 = objectinputstream.readObject();
    putForCreate(obj, obj1);
  }
}
Interview Key Points:
  • transient is a keyword used to exclude specific variables from the serialization process.
  • It is commonly employed for security reasons, preventing the serialization of sensitive data.
  • Transient variables are initialized to their default values during deserialization.
  • This keyword is beneficial when dealing with variables that do not need to be persisted, such as temporary or calculated values.
  • It enhances control over which parts of an object's state are serialized.
  • A special variable created using the transient keyword.
  • Prevents the variable from being serialized, excluding it during serialization.
  • Initialized with its default value during deserialization.
  • Used to exclude variables from the serialization process.
  • Differs from volatile, which deals with visibility in concurrent programming.
  • Both volatile and transient are rarely used compared to other keywords.
  • Employed to exclude instance variables from serialization.
  • Volatile signals the compiler to read the value from main memory.
  • Volatile can be used with static variables, but transient cannot.
  • Demonstrating the behavior of a transient variable in Java.

Comments