这篇文章开始讲java对象的序列化,这是因为近期自己的项目当中,大量使用了序列化技术,这里面有java提供的序列化技术,也有一些序列化框架;所以,下定决心把java的序列化技术整理一下,以供参考。这是序列化系列的第一篇文章,所以主要是描述java提供的序列化技术。后续系列再分别讲使用框架实现序列化。

按照惯例,先给出这篇文章的大致脉络

首先,描述了序列化技术的使用场景和序列化的几种方案。接着,讲java提供的序列化技术然后,就是需要注意的几个问题,比如transient关键字、序列化ID的作用、深度克隆等等最后,对java提供的系列化技术的一个总结

首先看文章第一部分。

一、认识序列化

1、从网络通信认识序列化

为了很好的理解序列化,先不讲概念,而是先从网络通信谈起,我们知道现在的网络通信技术基本上都是基于TCP/IP来实现的。假设我们有两台电脑,这两台电脑之间写好了java程序,一个是send端,一个是receive端,要实现他们的通信,其底层是怎么实现的呢?请看下面这张图。

从上面这张图我们可以看到,两个进程进行通信时候,想要发送数据,要先要把数据发送到TCP缓冲区,然后形成报文再发送出去,同样的道理,接收端也是一样。我们可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。同样的,当两个Java进程进行通信时,也可以使用序列化技术实现对象之间的传递。

为了理解起来方便,再来看一张图。

从这张图也可以清晰的看出,发送数据之前要序列化,接受数据要反序列化。到了这,我们再来看序列化的概念就比较好理解了,一句话:Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程;

2、序列化的使用场景

这个使用场景应该算是最重要的一环了,因为我们学习序列化就是为了使用他,现在把他们归纳一下:

(1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中; 、

(2)通过序列化以字节流的形式使对象在网络中进行传递和接收;

(3)通过序列化在进程间传递对象;

3、序列化有什么好处呢?

其实好处是根据使用场景来的;

(1)实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上

(2)利用序列化实现远程通信,即在网络上传送对象的字节序列。

4、序列化技术都有哪些?

文字总是看着很枯燥,还是看图吧。

看起来很多呀,不过后续的课程中,我会一个一个的讲,或者是挑主要的,而且里面我也没有全用过,大概会六七种吧。这篇文章也主要看第一个java的序列化机制。

二、java序列化机制

从上面的图中我们也已经看到了,java序列化主要有两个接口,这两个接口的实现方式,我都会给出,但是重点在于serialize接口的实现方式。在这一部分中,先给出序列化基本的代码实现,在下一部分当中再来看序列化有哪些需要注意的问题。OK,现在开始代码实现java的序列化机制。

1、使用Serializable接口实现序列化(重点,要牢记,第三部分会多次使用)

首先我们定义一个对象类User

接下来,在Test类中去实现序列化和反序列化。

当我们运行序列化方法时候,就可以看到,我们把数据存在了G://Test/template。

同时当我们运行反序列化方法的时候,就可以看到,反序列化成功,结果就不贴出来了,比较简单。

2、使用Externalizable接口实现序列化

首先,定义一个User1类

然后就是Test1类,和上面的Test一样,就不再贴出来了。在这里主要看Externalizable和Serializable接口的区别。下面对其进行归纳一下。

(1)Externalizable继承自Serializable接口

(2)需要我们重写writeExternal()与readExternal()方法

(3)实现Externalizable接口的类必须要提供一个public的无参的构造器。

因此,我们可以对writeExternal()与readExternal()方法重新更改一下;

到这,java序列化机制的基本使用就讲完了,从上面可以看出,使用起来还是非常简单的。不过,仅仅会基本的使用还不行,想要面试的时候更加的装13,还需要进一步深化。因此下面一部分主要就是对序列化机制的深入分析。还需要说一点,对于Serializable接口实现的序列化方式一定要牢记,因为下面要多次使用

三、深入分析java序列化机制

1、serialVersionUID的作用

一句话:其目的是序列化对象版本控制,有关各版本反序列化时是否兼容。如果在新版本中这个值修改了,新版本就不兼容旧版本,反序列化时会抛出InvalidClassException异常。如果修改较小,比如仅仅是增加了一个属性,我们希望向下兼容,老版本的数据都能保留,那就不用修改;如果我们删除了一个属性,或者更改了类的继承关系,必然不兼容旧数据,这时就应该手动更新版本号,即SerialVersionUid。

serialVersionUID有两种显示的生成方式:

一是默认的1L,比如:private static final long serialVersionUID = 1L;

二是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,

比如:private static final long serialVersionUID = xxxxL;

现在我们去验证一下序列化版本不一致的情况:

首先我们在User里面设置一下serialVersionUID=123456L。

然后再Test里面开始序列化。

接着我们更改serialVersionUID = 123456789L。然后再反序列化,就可以看到如下的错误了。同时也验证了序列化和反序列化需要版本一致的问题。

2、静态变量的序列化

首先需要说一下,静态变量不会被序列化。因为静态变量在全局区,本来流里面就没有写入静态变量,我打印静态变量当然会去全局区查找,当我write read 同时使用时,内存中的静态变量变了,所以打印出来的也变了。眼见为实,代码验证一下;

下面这个例子,主要是在对静态变量序列化之后,然后更改静态变量age的值,再重新反序列化输出一下。结果会出现两种情况:

(1)反序列输出的静态变量值没有变化:说明静态变量被序列化了。

(2)反序列输出的静态变量值变化了:说明静态变量没有被序列化了。

第一步:把User里面的年龄属性改成static静态类型

第二步:现在改一下Test类

然后看一下输出结果

3、Transient 关键字作用

Transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。

这个很好理解也很简单。下面代码来看一下他的作用

第一步:把User里面的年龄属性改成Transient 修饰。private transient int age;

第二步:Test不变,进行序列化和反序列化。

第三步:看结果。反序列化之后的输出age应该为0;

4、使用序列化实现深度克隆

对象的克隆也叫作对象的拷贝,拷贝有浅拷贝和深拷贝之分。

浅拷贝:使用一个已知实例对新创建实例的成员变量逐个赋值,这个方式被称为浅拷贝。深拷贝:当一个类的拷贝构造方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。这个方式称为深拷贝。浅拷贝存在对象属性拷贝不彻底问题。因此在这里我们的侧重点不是克隆问题,我们的关注点更在于深拷贝。现在抛弃之前的User。我们重新定义一个类Person。

第一步:定义一个CloneUtils

第二步:定义一个person类

第三步:在Test2类中实现深度克隆

四、总结

好了,到这里我们对java序列化机制已经有了基本的了解了,从一开始的网络机制,到最后的深拷贝。总之,java提供的序列化机制还是比较常用的,也是比较简单的。但是并不是说,平时开发的时候这一种就可以满足了,还有一些问题java提供的序列化机制是不能满足我们的要求的。比如说跨语言之间的序列化。因为在当前的开发中,可能需要C语言和java进行通信。就比如我现在的项目需要无人机和服务端通信。无人机上的ros系统,另外的开发人员就是通过C++开发的,但是后端我使用java实现的,这就涉及到了这个问题。

当然这里只给出序列化系列的第一篇,在文章一开始提到了多种序列化技术,没关系,慢慢来。喜欢的可以关注我,后续系列我会慢慢推出,谢谢支持

java 序列化_java的序列化机制,这一篇文章就够了相关推荐

  1. 【Java线程池】Java线程池汇总,看这一篇文章就够了

    https://blog.csdn.net/cmm0401/article/details/83377547

  2. Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...

  3. 如何使用 Maven 来创建项目(一篇文章就够了)

    如何使用 Maven 来创建项目(一篇文章就够了) 1. Maven 简介 1. 简介 2. 项目构建 3. 项目构建工具 2. Maven 的四大特性 1. 依赖管理系统 版本号规范 2. 多模块构 ...

  4. 集成Android免费语音合成功能(在线、离线、离在线融合),有这一篇文章就够了(离线)

    原址 集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(在线) 集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离在线融合)     ...

  5. 全面认识二极管,一篇文章就够了

    电子设计基础元器件 二极管,小小二极管,大大用途. ... 矜辰所致 目录 前言 一.二极管基础知识 1.1 什么是二极管 1.2 二极管的组成 1.3 二极管的原理 二.二极管特性 2.1 伏安特性 ...

  6. MySQL优化-一篇文章就够了(转发加收藏吧)

    关注我,一个仍存梦想的屌丝程序员,每天为你分享高质量编程博客. 回复 "代金券"  免费获取腾讯云和阿里云代金券 前言 说起MySQL的查询优化,相信大家收藏了一堆:不能使用SEL ...

  7. 集成Android免费语音合成功能(在线、离线、离在线融合),有这一篇文章就够了(在线)

    集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离线) 集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离在线融合)     转眼间 ...

  8. 学习 MongoDB 一篇文章就够了(珍藏版)

    文章目录 一.学习目录 二.扩展目录 一.学习目录 认识 MongoDB 一篇文章就够了 Windows平台安装MongoDB教程 Linux 上安装 MongoDB windows 安装 Mongo ...

  9. 架构师必须搞懂DNS,一篇文章就够了。

    转载自 架构师必须搞懂DNS,一篇文章就够了. 概念 DNS,全称Domain Name System,即域名系统,搞清楚,它不是DNF地下城与勇士. DNS是怎么来的,我们知道要访问一个服务器的资源 ...

  10. 全面认识MOS管,一篇文章就够了

    基础知识中 MOS 部分迟迟未整理,实际分享的电路中大部分常用电路都用到了MOS管, 今天势必要来一篇文章,彻底掌握mos管! ...更新:为什么常在MOS管GS并联电阻? ...更新:为什么要在MO ...

最新文章

  1. 如何使用python批量下载-使用 Python + Selenium 批量下载素材
  2. 简明 Python 编程规范
  3. 探索Julia(part5)--字典
  4. drools 7.x 加载指定的决策表
  5. 用户姓名信息保护python,喜大普奔!Maya 2022来了?!
  6. 简单实用的防止多次提交辅助类
  7. 【车牌识别】基于matlab GUI RGB颜色模型车牌识别【含Matlab源码 888期】
  8. SuperMap AR三维管线制作
  9. 最新伯乐PHP个人在线自动发卡网源码V3.1
  10. STM32与4脚光敏电阻的简单使用——初学
  11. 人脸识别的loss总结
  12. 数学分析_幂级数收敛分析
  13. 计算机基础知识面试题集合(包含计网OSI、TCP/IP、HTTP、TCP、UDP、三次握手、四次挥手、OS进程线程、死锁,常见数据结构及排序,Linux常用命令、数据库基础等。)
  14. 基础知识 | 什么是二进制文件?
  15. 程序员月薪5W却发出哀叹:家庭枷锁太重,生活如同围城
  16. Go语言6种字符串拼接的方式
  17. 【SAP】德国SAP校园招聘面试经验
  18. mybatis和spring框架的整合
  19. 热图展示单细胞转录组基因在不同组中表达阳性细胞差异
  20. 字面量、对象字面量、函数字面量、函数定义

热门文章

  1. 张量处理单元(TPU)
  2. 带小数十进制转二进制C语言,c语言十进制小数转为二进制
  3. iOS——百度地图点击标注事件
  4. 自己怎么制作地图,如何绘制电子版地图?
  5. 【游戏设计模式】之一 序言:架构,性能与游戏
  6. Winsock2_WSADATA
  7. Revisiting Stereo Depth Estimation From a Sequence-to Sequence Perspective with Transformer——阅读阶段
  8. 如何用Airtest脚本切换手机的输入法
  9. 利用计算机发布调度命令时必须严格遵守,调度命令
  10. kindeditor导入word文档 kindeditor word导入插件