先解释下什么是序列化

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

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

更多序列化请参考:《关于Java序列化你应该知道的一切》这篇文章。

什么是 transient?

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

具体来看下面的示例1

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;/*** @author 微信公众号:Java技术栈*/
public class TransientTest {public static void main(String[] args) throws Exception {User user = new User();user.setUsername("Java技术栈");user.setId("javastack");System.out.println("n序列化之前");System.out.println("username: " + user.getUsername());System.out.println("id: " + user.getId());ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d:/user.txt"));os.writeObject(user);os.flush();os.close();ObjectInputStream is = new ObjectInputStream(new FileInputStream("d:/user.txt"));user = (User) is.readObject();is.close();System.out.println("n序列化之后");System.out.println("username: " + user.getUsername());System.out.println("id: " + user.getId());}
}/*** @author 微信公众号:Java技术栈*/
class User implements Serializable {private static final long serialVersionUID = 1L;private String username;private transient String id;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getId() {return id;}public void setId(String id) {this.id = id;}}

输出结果:

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

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

静态变量能被序列化吗?

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

如果你也想加入我们的Java技术栈vip群和各位大牛一起讨论技术,那点击这个链接了解加入吧。

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

示例2:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;/*** @author 微信公众号:Java技术栈*/
public class TransientStaticTest {public static void main(String[] args) throws Exception {User2 user = new User2();User2.username = "Java技术栈1";user.setId("javastack");System.out.println("n序列化之前");System.out.println("username: " + user.getUsername());System.out.println("id: " + user.getId());ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d:/user.txt"));os.writeObject(user);os.flush();os.close();// 在反序列化出来之前,改变静态变量的值User2.username = "Java技术栈2";ObjectInputStream is = new ObjectInputStream(new FileInputStream("d:/user.txt"));user = (User2) is.readObject();is.close();System.out.println("n序列化之后");System.out.println("username: " + user.getUsername());System.out.println("id: " + user.getId());}
}/*** @author 微信公众号:Java技术栈*/
class User2 implements Serializable {private static final long serialVersionUID = 1L;public static String username;private transient String id;public String getUsername() {return username;}public String getId() {return id;}public void setId(String id) {this.id = id;}}

输出结果:

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

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

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

transient 真不能被序列化吗?

继续来看示例3:

import java.io.Externalizable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;/*** @author 微信公众号:Java技术栈*/
public class ExternalizableTest {public static void main(String[] args) throws Exception {User3 user = new User3();user.setUsername("Java技术栈");user.setId("javastack");ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream(new File("javastack")));objectOutput.writeObject(user);ObjectInput objectInput = new ObjectInputStream(new FileInputStream(new File("javastack")));user = (User3) objectInput.readObject();System.out.println(user.getUsername());System.out.println(user.getId());objectOutput.close();objectInput.close();}}/*** @author 微信公众号:Java技术栈*/
class User3 implements Externalizable {private static final long serialVersionUID = 1L;public User3() {}private String username;private transient String id;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getId() {return id;}public void setId(String id) {this.id = id;}@Overridepublic void writeExternal(ObjectOutput objectOutput) throws IOException {objectOutput.writeObject(id);}@Overridepublic void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {id = (String) objectInput.readObject();}}

输出结果:

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 修饰,静态变量都不能被序列化;

好了,栈长花了半天时间,终于整理完了。如果对你有帮助,那就转发分享一下吧!如果你也想加入我们的Java技术栈vip群和各位大牛一起讨论技术,那点击这个链接了解加入吧

另外,栈长已经整理了大量 Java 系列核心技术知识点文章,关注Java技术栈即可获取最新版。

java transient关键字_小伙子,你真的搞懂 transient 关键字了吗?相关推荐

  1. inputstream重新赋值之前需要close吗_变量提升真的搞懂了吗?打脸的一道题

    变量提升真的搞懂了吗?打脸的一道题 我们知道JS代码在执行之前,会做一系列的事情,其中就包括变量提升,原本以为把变量提升搞懂的我(因为这两天一直在研究变量提升,自我感觉已经很良好了,哈哈哈),拿到了一 ...

  2. java 原型图_一张图搞懂原型、原型对象、原型链

    基本概念 在javascript中,函数可以有属性. 每个函数都有一个特殊的属性叫作原型(prototype) 每个对象拥有一个原型对象 [[Prototype]] / __proto__ / Obj ...

  3. 一文搞懂transient关键字

    一文搞懂transient关键字 1.序列化 1.1 什么是序列化 1.2 以文件存储为例实现序列化 2.transient关键字 2.1 添加transient关键字 2.2 静态变量不需要加tra ...

  4. java:彻底搞懂volatile关键字

    对于volatile这个关键字,相信很多朋友都听说过,甚至使用过,这个关键字虽然字面上理解起来比较简单,但是要用好起来却不是一件容易的事. 这篇文章将从多个方面来讲解volatile,让你对它更加理解 ...

  5. java虚数复数计算_虚部?从搞懂虚数开始....

    本文转自公众号 imath, 作者 阮一峰. 一直觉得虚数(imaginary number)很难懂. 中学老师说,虚数就是-1的平方根. 可是,什么数的平方等于-1呢?计算器直接显示出错! 直到今天 ...

  6. 夯实Java基础系列17:一文搞懂Java多线程使用方式、实现原理以及常见面试题

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  7. layer output 激活函数_一文彻底搞懂BP算法:原理推导+数据演示+项目实战(下篇)...

    在"一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)"中我们详细介绍了BP算法的原理和推导过程,并且用实际的数据进行了计算演练.在下篇中,我们将自己实现BP算法(不使用第 ...

  8. java 线框图_你真的搞懂什么是线框图,什么是原型图了吗?

    设计师朋友们都知道,在网站开发或者手机应用开发的前期阶段,需要创建线框图和原型图给客户展示.但有时候客户会提出略过线框图和原型图设计的阶段,直接过渡到网站的界面设计甚至是开发阶段.这种想法,往往是源于 ...

  9. string substring的用法_夯实Java基础系列3:一文搞懂String常见面试题,从基础到实战...

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

最新文章

  1. 关于端口映射的一个命令
  2. Linux之SELinux的基本应用
  3. linux卸载openjdk_Linux系列(七)——linux其他指令【rpm、yum、sudo】
  4. 注解mysql事物管理_Spring 使用注解方式进行事务管理
  5. Net-SNMPv3的使用
  6. RTP、RTCP及媒体流同步
  7. android打飞机游戏、MVP句子迷App、悬浮窗、RxJava+Retrofit、加载动画、定制计划App等源码
  8. windows server 2008 web服务器搭建
  9. 02、江苏专转本(专业课笔记)第二章、计算机的组成原理
  10. Kafaka的消息消费方式
  11. Commonjs 模块化开发解析
  12. Axure8原型设计实战案例:如何设计用户管理,手把手带你学习
  13. Primitives vs Objects
  14. 2020中兴软件测试面经
  15. 数据挖掘十大算法--PageRank
  16. 官宣!香港大学,将落户深圳
  17. 推荐系统学习(一)——推荐引擎初探
  18. 安装rpm 树莓派4_树莓派|在树莓派中开启激动人心的 Perl 之旅
  19. 来看一看那些已经倒闭的互联网公司
  20. Streamsets介绍

热门文章

  1. VSCode如何自动换行,右侧换行间距长度,隐藏右侧代码预览(Minimap代码缩略图滚动条),比对代码差异窗口也自动换行
  2. git用户文档1 — git基础
  3. MQTT topic匹配规则
  4. Linux tcpdump命令详解与Wireshark
  5. ORM操作models一对多、多对多关系
  6. Aveva Marine C# 二次开发入门001
  7. linux free命令详解和使用实例(查看内存使用率)
  8. iOS----------计算一段代码执行时间
  9. Zookeeper 安装和配置
  10. vue.js 源代码学习笔记 ----- 工具方法 lang