Understanding transient variables in Java and how they are practically used in HashMap---reference
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的更多相关文章
- Life Cycle of Thread – Understanding Thread States in Java
Life Cycle of Thread – Understanding Thread States in Java 深入理解java线程生命周期. Understanding Life Cycle ...
- 【JDK1.8】 Java小白的源码学习系列:HashMap
目录 Java小白的源码学习系列:HashMap 官方文档解读 基本数据结构 基本源码解读 基本成员变量 构造器 巧妙的tableSizeFor put方法 巧妙的hash方法 JDK1.8的putV ...
- Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结
2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...
- 如何在JAVA中实现一个固定最大size的hashMap
如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...
- Java中最常用的集合类框架之 HashMap
一.HashMap的概述 HashMap可以说是Java中最常用的集合类框架之一,是Java语言中非常典型的数据结构. HashMap是基于哈希表的Map接口实现的,此实现提供所有可选的映射 ...
- Java 集合源码分析(一)HashMap
目录 Java 集合源码分析(一)HashMap 1. 概要 2. JDK 7 的 HashMap 3. JDK 1.8 的 HashMap 4. Hashtable 5. JDK 1.7 的 Con ...
- Java集合源码学习(四)HashMap分析
ArrayList.LinkedList和HashMap的源码是一起看的,横向对比吧,感觉对这三种数据结构的理解加深了很多. >>数组.链表和哈希表结构 数据结构中有数组和链表来实现对数据 ...
- Java集合源代码剖析(二)【HashMap、Hashtable】
HashMap源代码剖析 ; // 最大容量(必须是2的幂且小于2的30次方.传入容量过大将被这个值替换) static final int MAXIMUM_CAPACITY = 1 << ...
- Java集合源码分析(四)HashMap
一.HashMap简介 1.1.HashMap概述 HashMap是基于哈希表的Map接口实现的,它存储的是内容是键值对<key,value>映射.此类不保证映射的顺序,假定哈希函数将元素 ...
随机推荐
- JDBC 与ODBC的区别
一.ODBC(Open DataBase Connectivity : 开放数据库连接) ODBC 总体结构 应用程序 执行处理并调用odbc函数,提交sql语 ...
- Java was started but returned exit code=13 C:\ProgramData\Oracle\Java\javapath\javaw.exe
---------------------------Eclipse---------------------------Java was started but returned exit code ...
- java 注解(转)
第一部分:了解一下java1.5起默认的三个annotation类型: 一个是@Override:只能用在方法之上的,用来告诉别人这一个方法是改写父类的. 一个是@Deprecated:建 ...
- Js 与 TextArea
当给一个js变量赋值一个有换行的值得时候,就会报错: <!DOCTYPE HTML> <html> <head> <script src="http ...
- 菜鸟学习HTML5+CSS3(一)
主要内容: 1.新的文档类型声明(DTD) 2.新增的HTML5标签 3.删除的HTML标签 4.重新定义的HTML标签 一.新的文档类型声明(DTD) HTML 5的DTD声明为:<!d ...
- 50道经典的JAVA编程题(41-45)
50道经典的JAVA编程题(41-45),苦逼的程序猿,晚上睡不着了编程吧~今天坚持做10道题!发现编程能是我快乐...O(∩_∩)O哈哈~能平静我烦乱的心,剩下5道题留到考试完了再做吧!该睡觉了.. ...
- HDU-4671 Backup Plan 构造解
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4671 假设是3 m,首先按照第一列按照1 2 3 1 2 3 1...排下去,然后个数就是一个 (m/ ...
- 纯CSS完美实现垂直水平居中的6种方式
前言 由于HTML语言的定位问题,在网页中实现居中也不是如word中那么简单,尤其在内容样式多变,内容宽高不定的情况下,要实现合理的居中也是颇考验工程师经验的.网上讲居中的文章很多,但是都不太完整,所 ...
- 通过dbcc page来查看表中的数据
--1.先建表 CREATE TABLE test(idd INT NOT NULL,name VARCHAR(10) NULL) INSERT INTO TEST SELECT 1,'abcdefg ...
- Stones
题目是:HDU1896 题目简述:输入一堆石头,每个石头有自己所在的位置p,以及自己可以抛多远的距离d.你每遇到第奇数个石头,就把石头丢出去,第偶数个石头就不管.计算出最后一个石头它所处的位置. 解法 ...