小伙子,你真的搞懂 transient 关键字了吗?

作者:Java技术栈
来源:https://www.jianshu.com/p/f77c2a05ea49

先解释下什么是序列化

我们的对象并不只是存在内存中,还需要传输网络,或者保存起来下次再加载出来用,所以需要Java序列化技术。

Java序列化技术正是将对象转变成一串由二进制字节组成的数组,可以通过将二进制数据保存到磁盘或者传输网络,磁盘或者网络接收者可以在对象的属类的模板上来反序列化类的对象,达到对象持久化的目的。

什么是 transient?

简单来说就是,被 transient 修饰的变量不能被序列化。

具体来看下面的示例1

小伙子,你真的搞懂 transient 关键字了吗?

小伙子,你真的搞懂 transient 关键字了吗?

输出结果:

序列化之前
username: Java技术栈
id: javastack
序列化之后
username: Java技术栈
id: null

示例1在 id 字段上加了 transient 关键字修饰,反序列化出来之后值为 null,说明了被 transient 修饰的变量不能被序列化。

静态变量能被序列化吗?

这个话题也是最近栈长的Java技术栈vip群里面讨论的,大家对这个知识点比较模糊,我就写了这篇文章测试总结一下。

小伙子,你真的搞懂 transient 关键字了吗?

那么,到底静态变量能被序列化吗?废话少说,先动手测试下吧!

示例2:

小伙子,你真的搞懂 transient 关键字了吗?

小伙子,你真的搞懂 transient 关键字了吗?

输出结果:

序列化之前
username: Java技术栈1
id: javastack
序列化之后
username: Java技术栈2
id: null

示例2把 username 改为了 public static, 并在反序列化出来之前改变了静态变量的值,结果可以看出序列化之后的值并非序列化进去时的值。

由以上结果分析可知,静态变量不能被序列化,示例2读取出来的是 username 在 JVM 内存中存储的值。

transient 真不能被序列化吗?

继续来看示例3:

小伙子,你真的搞懂 transient 关键字了吗?

小伙子,你真的搞懂 transient 关键字了吗?

输出结果:

null
javastack

示例3的 id 被 transient 修改了,为什么还能序列化出来?那是因为 User3 实现了接口 Externalizable,而不是 Serializable。

在 Java 中有两种实现序列化的方式,Serializable 和 Externalizable,可能大部分人只知道 Serializable 而不知道 Externalizable。

这两种序列化方式的区别是:实现了 Serializable 接口是自动序列化的,实现 Externalizable 则需要手动序列化,通过 writeExternal 和 readExternal 方法手动进行,这也是为什么上面的 username 为 null 的原因了。

transient 关键字总结

1)transient修饰的变量不能被序列化;

2)transient只作用于实现 Serializable 接口;

3)transient只能用来修饰普通成员变量字段;

4)不管有没有 transient 修饰,静态变量都不能被序列化;


分享到:


相關文章: