In the post Serialization in Java it has already been discussed that serialization is the mechanism by which any object can be converted to byte stream. By default all of the object variables are converted to bytes and persisted/send across network.There may be a scenario where you don’t want a variable to be part of serialization because that variable may have some sensitive information which you don’t want to persist or send across the network. That variable can be marked as transient in Java.
Transient keyword in Java
If you want to exclude any object field from getting serialized you can mark that field as transient in Java. Note that you cannot use transient keyword with methods or local variables it can only be used with member variables.
Java transient keyword example
Let’s see an example using transient keyword. Here we have a class called User which has a field pwd which you don’t want to get serialized.
There is a also a class Util that has static methods for serializing and deserializing an object.
User class
import java.io.Serializable; import java.util.Date; public class User implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private String userName; private Date loginDate; // Transient field private transient String pwd; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Date getLoginDate() { return loginDate; } public void setLoginDate(Date loginDate) { this.loginDate = loginDate; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }
Util class
import java.io.File; 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 Util { /** * Method used for serialization * @param obj * @param fileName */ public static void serialzeObject(Object obj, String fileName){ try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( new File(fileName)))){ oos.writeObject(obj); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Method used for deserializing * @param fileName * @return * @throws ClassNotFoundException */ public static Object deSerialzeObject(String fileName) throws ClassNotFoundException{ Object obj = null; try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream( new File(fileName)))){ obj = ois.readObject(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return obj; } }
Now let’s create a User object and serialize and deserialize it to see what happens to the pwd field.
import java.util.Date; public class SerializationDemo { public static void main(String[] args) { // Creating and initializaing a User object User user = getUser(); // file name final String fileName = "D://user.ser"; // serializing Util.serialzeObject(user, fileName); try { // deserializing user = (User)Util.deSerialzeObject(fileName); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("User name " + user.getUserName()); System.out.println("Login date " + user.getLoginDate()); System.out.println("Password " + user.getPwd()); } private static User getUser(){ User user = new User(); user.setUserName("TestUser"); user.setLoginDate(new Date()); user.setPwd("pwd@123"); return user; } }
Output
User name TestUser Login date Mon Apr 03 18:08:49 IST 2017 Password null
If you open the created file “user.ser” you won’t find any trace of pwd variable there.
When to use transient keyword in Java
- As mentioned above you can use transient keyword with the variable that holds some confidential value which you don’t want to get persisted in a file or sent across the network.
- Any variable that is calculated using other variables can be marked as transient in Java. After deserialization you can get the other variables and recalculate the value. One of the example of this can be found in Java Collection framework itself. In code of HashMap class you can see that hash code is calculated again after deserializing the HashMap key and values. Hashcode is not serialized but recalculated in that case.
Let’s say you have a Person bean where you have both Date Of Birth and age fields. In that case age can be calculated again using the DOB and current date rather than serializing the age. If you are serializing the Person object for long age may be wrong if taken from the deserialized object.
Person class
import java.io.Serializable; import java.util.Date; public class Person implements Serializable{ private static final long serialVersionUID = 1L; private String name; private Date dob; // transient private transient int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getDob() { return dob; } public void setDob(Date dob) { this.dob = dob; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
SerializationDemo class
import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.Calendar; import java.util.GregorianCalendar; public class SerializationDemo { public static void main(String[] args) { // Creating and initializaing a Person object Person person = getPerson(); // file name final String fileName = "D://person.ser"; // serializing Util.serialzeObject(person, fileName); try { // deserializing person = (Person)Util.deSerialzeObject(fileName); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Name " + person.getName()); System.out.println("DOB " + person.getDob()); System.out.println("Age " + person.getAge()); int age = (int)calculateAge(person); System.out.println("age " +age); } /** * Method for getting person record * @return */ private static Person getPerson(){ Person person = new Person(); DateFormat df = new SimpleDateFormat("dd/MM/yyyy"); try { person.setDob(df.parse("04/04/2015")); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } person.setName("TestUser"); return person; } /** * Method for calculating age * @param person * @return */ private static long calculateAge(Person person){ // creating a calendar instance with DOB Calendar firstCal = GregorianCalendar.getInstance(); firstCal.setTime(person.getDob()); // Calculating difference in years long num = ChronoUnit.YEARS.between( LocalDate.of(firstCal.get(Calendar.YEAR), firstCal.get(Calendar.MONTH), firstCal.get(Calendar.DAY_OF_MONTH)) , LocalDate.now()) ; return num; } }
Util class is already given above with the serialize() and deserialize() methods.
Output
Name TestUser DOB Sat Apr 04 00:00:00 IST 2015 Age 0 age 2
You can see in the output initially age is 0 after deserialization as age was marked as transient. It’s later calculated using the DOB and current date. - You may have instances that have no meaning if serialized. Like a logger instance, a resource bundle, a properties instance with property values, it's better to mark such instances as transient.
That's all for this topic Transient Keyword in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!
>>>Return to Java Advanced Tutorial Page
Related Topics
You may also like-