阅读HashMap源码过程中,看到以下一行代码,对显眼的transient关键字产生好奇,于是上网查阅,看到一篇好文,便记录下来,以便之后查看。
/**
* The table, initialized on first use, and resized as
* necessary. When allocated, length is always a power of two.
* (We also tolerate length zero in some operations to allow
* bootstrapping mechanics that are currently not needed.)
*/
transient Node<K,V>[] table;
来源:https://baijiahao.baidu.com/s?id=1636557218432721275&wfr=spider&for=pc
作者:愚公要移山1
1.初识 transient 关键字
简单的一句话:将不需要序列化的属性前添加关键字transient,序列化对象时,这个属性就不会被序列化。
用代码验证一下:
执行结果:
2.深入分析transient关键字
为了更加深入的去分析transient关键字,我们带着几个问题去解读:
- transient底层实现的原理是什么?
- 被transient修饰的变量真的不能被序列化吗?
- 静态变量能被序列化吗?被transient关键字修饰之后呢?
2.1 transient底层实现原理是什么?
java的serialization提供了一个非常棒的存储对象状态的机制,说白了serialization就是把对象的状态存储到硬盘上去,等需要的时候再把它读出来使用。但有些时候像银行卡号这类字段不希望在网络上传输,transient的作用就是把这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
2.2 被transient修饰的变量真的不会被序列化吗?
想要解决这个问题,首先还要重提一下对象的序列化方式:
- 实现Serializable接口
- 实现Exteranlizable接口
需要重写writeExternal和readExternal方法
效率比Serializable高一些,并且可以决定哪些属性需要序列化(即使是transient修饰的)
对大量对象,或者重复对象,则效率低
进行验证:
执行结果:
也就是说,实现了Externalizable接口,哪一个属性被序列化是我们手动去指定的,即使是transient关键字修饰也不起作用。
2.3静态变量能被序列化吗?被transient关键字修饰之后呢?
静态变量是不会被序列化的,即使没有transient关键字修饰。
进行验证:
执行结果:
原因:
因为静态变量在全局区,本来流里面就没有写入静态变量,我打印静态变量当然会去全局区查找,而我们的序列化是写到磁盘上的,所以JVM查找这个静态变量的值,是从全局区查找的,而不是磁盘上。user.setAge(18);年龄改成18之后,被写到了全局区,其实就是方法区,只不过被所有的线程共享的一块空间。
因此:静态变量不管是不是transient关键字修饰,都不会被序列化
3. transient关键字总结
java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。像银行卡、密码等等这些数据。这个需要根据业务情况了。