What is the significance of the transient keyword in Java? If you know the answer, good! you are a person who uses this a lot or a person who has read this very recently. If this seems like a word from a half remembered dream, well don’t worry you have company. I was and am will be confused if you asked me about this in an hour. It is one of those things that I learnt but never had to use it – mainly because I never worked on code that required me to worry about how my objects were serialized. I could delegate that to the libraries.

This post is an attempt to explain what transient is (which most people should know) and an example of how it is used, using the most abused class of my daily work – thejava.util.HashMap class.

What is transient?

The transient keyword in Java is used on class variables and is used to indicate to the runtime that this variable should not be considered while serializing the object is being written to abyte stream. To put it in simpler words, if an object is being written to a byte stream then all transient variables will be ignored.

Lets think about this for a moment. Lets say you have a class that looked like this

public class Bean{

private int a=5;

private transient int b=6;

}

If you were creating an instance of this class and then writing it to a byte stream – a file or a socket, then when serializing this class, the variable ‘a’ will be sent but ‘b’ will be ignored. When you reconstruct this class on the other end, then ‘b’ will be reverted back to the initial default value. So lets say you had some code that updated the value of b to 10 before serializing the object, then when you reconstruct it, the value of b will be 6.

Why would you not want fields to be preserved?

Why would you not want some of the fields in an object to be preserved between storing and retrieving the object? If a field represented a value like a persons name or a amount or some such parameter which has some significance and changing it will impact the application state, then you would definitely want to preserve it. But do you have parameters that you can afford to lose?

Lets say you have a flag that indicates whether the object was modified or not – this is typical in ORM libraries that want to track whether a bean was modified after you retrieved it from the database. The value of the flag that indicates whether the object was modified or not is significant only until the change to the object is saved somewhere and the object is now again clean. So such a flag, lets call it the dirty indicator, is a field that gets reset once it is saved.

If this object was being written to a database to save it, like in an ORM, or written to a file or sent over a socket, then once that is done, then the flag is not needed. Also any code that retrieves the object next time, will expect the flag to be set to the default value which is false for a new instance. So this is a good case to use  transient variable. Set the flag to true while the object is in memory and while writing it to a file, ignore the field. When you read the file again, the field is read a false, which is true because you haven’t yet changed the field.

Do we ever want to use transient for fields that are not reset and need to be preserved?

The answer is yes. And now we will proceed to understand why.

Lets say you have a bean class, like the one I showed above. When this is sent over a socket for example, Java serializes this to a stream of bytes in such a way that it can reconstruct the object on the other end. In order to do this it sends information like -

  • The class name
  • The field names
  • The field values and the lengths

Based on the class name, the JVM on the other end instantiates an object and sets all the values on the respective fields. Since you are sending all the field names and values, it will take a good amount of memory to hold this. If the size of the serialized byte array is larger then it will take more time to send this over the socket and it will take more time to reconstruct it. It will also consume more bandwidth.

There are applications where spending time sending large blocks of data is expensive – so you want to minimize the amount of space occupied by serialized objects and also the time taken to serialize and de-serialize objects. You will write custom code to serialize your objects by writing writeObject(ObjectOutputStream) and readObject(ObjectInputStream) methods.

When you do this, you should mark all your fields as transient and then write them on your own to the object output stream. You can read them back in the same order and reconstruct the object.

Another case is for collections where you store data in an indexed fashion and the index will change when you de-serialize the object – in this case too you will want to mark things as transient and reconstruct them on your own.

So how does a hash map use transients?

There is no good reason why I chose hash map as an example other than the fact that I am most familiar with this and have flogged this to death by using it a lot.

If you look at the source code of java.util.HashMap(http://www.docjar.com/html/api/java/util/HashMap.java.html), you will see that the data that you put in is stored in a array of Entry<K,V> objects. This array is a transient variable called table. There is a table size which is transient too, and there are a bunch of other non-transient and transient variables.

Why is the table a transient? If you look at the code, you will see that for every key that you put in , the class creates a hash code, and using the length of the array (default 16 at start up) it determines the index of the key in the array as

index = hash & (length -1)

Where hash is the return value of Object.hashCode().

There are two important things here – hashCode() does not return the same value for two instances of the same class. And, if a key is not stored in the correct index as per the hash, then it is more expensive to retrieve it. In fact, if you thin about it, if you created hash code on one computer and put the key at a particular index, and then on a different PC calculated the hash code and index, it will return a different value. If you serialized the table as is and reconstructed it, then you will be referring to the wrong index!

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.

For this reason, HashMap implements the writeObject and readObject methods. These still let the non transient fields to get serialized as they would normally do, but they wrote the key value pairs at the end of the byte array one after the other. When reading back, they let the non transient variables to be handled by Java default de-serialization logic and then read the key value pairs one by one.

For each key the hash and the index is calculated again and is inserted to the correct position in the table so that it can be retrieved again without any error.

Conclusion

Although we have not touched upon all uses of transient, we have seen a very good example usage of this in a core Java class.

ref from:http://supercoderz.in/2012/10/02/understanding-transient-variables-in-java-and-how-they-are-practically-used-in-hashmap/

Understanding transient variables in Java and how they are practically used in HashMap---reference的更多相关文章

  1. Life Cycle of Thread – Understanding Thread States in Java

    Life Cycle of Thread – Understanding Thread States in Java 深入理解java线程生命周期. Understanding Life Cycle ...

  2. 【JDK1.8】 Java小白的源码学习系列:HashMap

    目录 Java小白的源码学习系列:HashMap 官方文档解读 基本数据结构 基本源码解读 基本成员变量 构造器 巧妙的tableSizeFor put方法 巧妙的hash方法 JDK1.8的putV ...

  3. Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结

    2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...

  4. 如何在JAVA中实现一个固定最大size的hashMap

    如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...

  5. Java中最常用的集合类框架之 HashMap

    一.HashMap的概述 HashMap可以说是Java中最常用的集合类框架之一,是Java语言中非常典型的数据结构.      HashMap是基于哈希表的Map接口实现的,此实现提供所有可选的映射 ...

  6. Java 集合源码分析(一)HashMap

    目录 Java 集合源码分析(一)HashMap 1. 概要 2. JDK 7 的 HashMap 3. JDK 1.8 的 HashMap 4. Hashtable 5. JDK 1.7 的 Con ...

  7. Java集合源码学习(四)HashMap分析

    ArrayList.LinkedList和HashMap的源码是一起看的,横向对比吧,感觉对这三种数据结构的理解加深了很多. >>数组.链表和哈希表结构 数据结构中有数组和链表来实现对数据 ...

  8. Java集合源代码剖析(二)【HashMap、Hashtable】

    HashMap源代码剖析 ; // 最大容量(必须是2的幂且小于2的30次方.传入容量过大将被这个值替换) static final int MAXIMUM_CAPACITY = 1 << ...

  9. Java集合源码分析(四)HashMap

    一.HashMap简介 1.1.HashMap概述 HashMap是基于哈希表的Map接口实现的,它存储的是内容是键值对<key,value>映射.此类不保证映射的顺序,假定哈希函数将元素 ...

随机推荐

  1. error LNK2001: 无法解析的外部符号 _IID_IDirectDraw7

    工程使用了DirectDraw,编译出错 error LNK2001: 无法解析的外部符号 _IID_IDirectDraw7 解决办法是吧dxguid.lib添加到工程中,把lib所在目录添加到工程 ...

  2. linux删除数据文件无备份恢复

    参考 : http://www.lunar2013.com/2013/06/linux-%E8%AF%AF%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%E6%81%A2%E ...

  3. 单元测试工具之Xunit

    在.NET开发中的单元测试工具之——xUnit.Net  原始出处 http://zhoufoxcn.blog.51cto.com/792419/1172320 在上一篇<在.NET开发中的单元 ...

  4. leetcode—Same Tree

    1.题目描述 Given two binary trees, write a function to check if they are equal or not.   Two binary tree ...

  5. DOS命令关闭进程

    1.开始-运行,输入cmd后回车; 2.在DOS提示符下,先用命令 tasklist 回车来获取进程的 PID(例如获取了Explorer.EXE进程的PID为1988); 3.然后再输入命令:tas ...

  6. 解决adb问题的方法

    The connection to adb is down,and a server error has occured. 在网上找的那个高端方法根本不管用,来,试试我的方法.. 先装个360手机助手 ...

  7. svn文件清理Bat脚本

    @echo On@Rem C:\Users\caoxiancc\Desktop\Ueditor-thinkphp-master\Ueditor --svn跟路径@PROMPT [Com] @for / ...

  8. ubuntu 运行android sdk 下的工具adb报bash: ./adb: No such file or directory

    运行adb出现这种错误: bash: ./adb: No such file or directory   但adb确实存在. 可能1:你用的是64位的Linux,没装32位运行时库,安装 $ sud ...

  9. hbase运行模式

    Hbase有两种运行模式:standalone和distributed.standalone模式参见Quick Start Guide.以distributed模式设置Hbase,需要编辑Hbase ...

  10. A Tour of Go Methods

    Go does not have classes. However, you can define methods on struct types. The method receiver appea ...