Java序列化系列教程(上)
一定义以及相关概念
互联网的产生带来了机器间通讯的需求,而互联通讯的双方需要采用约定的协议,序列化和反序列化属于通讯协议的一部分。通讯协议往往采用分层模型,不同模型每层的功能定义以及颗粒度不同,例如:TCP/IP协议是一个四层协议,而OSI模型却是七层协议模型。在OSI七层协议模型中展现层(Presentation Layer)的主要功能是把应用层的对象转换成一段连续的二进制串,或者反过来,把二进制串转换成应用层的对象,这两个功能就是序列化和反序列化。一般而言,TCP/IP协议的应用层对应与OSI七层协议模型的应用层,展示层和会话层,所以序列化协议属于TCP/IP协议应用层的一部分。本文对序列化协议的讲解主要基于OSI七层协议模型。
序列化: 将数据结构或对象转换成二进制串的过程。
反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。
二应用场景2.1对象持久化
Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java对象序列化就能够帮助我们实现该功能。在实际的生产场景中很多情况下会用到缓存,用到redis来实现缓存的都知道,在往缓存里放数据的时候不管是key还是value都要首先完成序列化,只有序列化后才能依靠redis来存放,当获取数据的时候要反序列化。
2.2对象网络传输
当在实际中使用RMI(远程方法调用)的时候,比如hession调用,dubbo调用,或在网络中传递对象时,都会用到对象序列化,和反序列化。
三如何实现序列化
在Java中,只要一个类实现了java.io.Serializable接口,那么它就可以被序列化。首先定义一个User类。
1package com.duomeng.product;
2import java.io.*;
3public class User implements Serializable{
4 private static final long serialVersionUID = -6513548580766215238L;
5 public String name;
6 public String pawssWord;
7 public String getName() {
8 return name;
9 }
10 public void setName(String name) {
11 this.name = name;
12 }
13 public String getPawssWord() {
14 return pawssWord;
15 }
16 public void setPawssWord(String pawssWord) {
17 this.pawssWord = pawssWord;
18 }
19}
接着写一个测试类来完成序列化和反序列化的测试,就定义为UserTest.class
1package com.duomen.product;
2import java.io.*;
3public class UserTest {
4 public static void main(String[] args) {
5 User user = new User();
6 user.setName("duomeng");
7 user.setPawssWord("123qwe");
8 try {
9 //序列化
10 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("user.obj"));
11 objectOutputStream.writeObject(user);
12 objectOutputStream.flush();
13 objectOutputStream.close();
14 //反序列化
15 ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("user.obj"));
16 User oldUser = (User) objectInputStream.readObject();
17 objectInputStream.close();
18 System.out.println("name = [" + oldUser.getName() + "]");
19 System.out.println("password = [" + oldUser.getPawssWord() + "]");
20 } catch (IOException e) {
21 e.printStackTrace();
22 } catch (ClassNotFoundException e) {
23 e.printStackTrace();
24 }
25 }
26}
如果没有什么的问题的,那么结果也一定不出所料的输出如下内容
1name = [duomeng]
2password = [123qwe]
四相关知识
1.通过ObjectOutputStream和ObjectInputStream对对象进行序列化及反序列化
2.一个类如果被实例化,那么这个类必须实现java.io.Serializable,否在在实例化的时候会抛出java.io.NotSerializableException异常,因为在序列化的过程中大概有如下的调用列writeObject ---> writeObject0 --->writeOrdinaryObject--->writeSerialData--->invokeWriteObject,可以看下一下writeObject0方法里的部分代码,如下
1// remaining cases
2 if (obj instanceof String) {
3 writeString((String) obj, unshared);
4 } else if (cl.isArray()) {
5 writeArray(obj, desc, unshared);
6 } else if (obj instanceof Enum) {
7 writeEnum((Enum<?>) obj, desc, unshared);
8 } else if (obj instanceof Serializable) {
9 writeOrdinaryObject(obj, desc, unshared);
10 } else {
11 if (extendedDebugInfo) {
12 throw new NotSerializableException(
13 cl.getName() + "\n" + debugInfoStack.toString());
14 } else {
15 throw new NotSerializableException(cl.getName());
16 }
17 }
3.虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID)如果不显示的指定序列化Id,那么在序列化的过程中jvm会根据当前的对象的类的属性和方法计算出一个serialVersionUID,同样当反序列化的时候也会根据目标类的属性和方法结算一个serialVersionUID,如果在序列化之后,对应的类的属性或者方法发生变化那么计算出来的serialVersionUID是不一样的,这样在反序列化的时候就会抛异常,反序列化失败,通常的做法是通过IDE来显示的生成,这样不仅可以防止修改类的属性或者方法导致反序列化失败,从而也可以依靠serialVersionUID的不同来对一些访问做限制,比如变化了serialVersionUID之后,那些不知道最新serialVersionUID的访问将会失败。
4.要想将父类对象也序列化,就需要让父类也实现java.io.Serializable接口,否则父类的属性并不能完成序列化。
五总结
在实际的应用当中序列化的实现还有很多,比如通常用到的json和xml也同样是一种序列化,就像开头所说的只要是将数据结构或对象转换成二进制串的过程就叫序列化,只要是将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程就是反序列化。
Java序列化系列教程(上)的更多相关文章
- Java序列化系列教程(下)
一引言 将 Java 对象序列化为二进制文件的 Java 序列化技术是 Java 系列技术中一个较为重要的技术点,在大部分情况下,开发人员只需要了解被序列化的类需要实现 Serializable 接口 ...
- 阿里 Java 手册系列教程:为啥强制子类、父类变量名不同?
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 父子类变量名相同会咋样? 为啥强制子类.父类变量名不同? ...
- 推介一个学习JAVA的系列教程-狗鱼IT教程
介绍一个学JAVA的零基础学习JAVA的网站,推介一个学习JAVA的系列教程-狗鱼IT教程 下面是java的系教程: 1、[java教程]Java 教程 2、[java教程]Java 简介 3、[ja ...
- Java NIO系列教程(七) selector原理 Epoll版的Selector
目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...
- Java NIO系列教程(三) Channel之Socket通道
目录: <Java NIO系列教程(二) Channel> <Java NIO系列教程(三) Channel之Socket通道> 在<Java NIO系列教程(二) Ch ...
- Java NIO系列教程(二) Channel通道介绍及FileChannel详解
目录: <Java NIO系列教程(二) Channel> <Java NIO系列教程(三) Channel之Socket通道> Channel是一个通道,可以通过它读取和写入 ...
- Java NIO系列教程(十一) Java NIO 与 IO
Java NIO系列教程(十一) Java NIO与IO 当学习了 Java NIO 和 IO 的 API 后,一个问题马上涌入脑海: 我应该何时使用 IO,何时使用 NIO 呢?在本文中,我会尽量清 ...
- Java NIO系列教程(三-十二) Buffer
原文链接 作者:Jakob Jenkov 译者:airu 校对:丁一 Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到 ...
- Java NIO系列教程(八)JDK AIO编程
目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...
随机推荐
- 多.h项目出现的问题:使用了预编译头依然出现error LNK2005:***obj已在***obj中定义与c++ error C2011: “xxx”:“class”类型重定义解决办法
使用了预编译头依然出现error LNK2005:***obj已在***obj中定义 造成该问题的可能性比较多,本人将在今后遇到时添加进来,今天先放出本人遇到的一种情况. 多重包含含有变量定义的.h文 ...
- JS 比较运算符 逻辑运算符
逻辑运算符 三元运算符 摘自:http://www.w3school.com.cn/js/js_comparisons.asp
- <struct、union、enum>差异
关于C++和C的区别 区别最大的是struct,C++中的struct几乎和class一样了,可以有成员函数,而C中的struct只能包含成员变量. enum,union没区别. struct的定义 ...
- 表情符号Emoji的正则表达式
/** * 判断字符串包含表情 * @param value * @return */ public static boolean containsEmoji(String value){ boole ...
- NormalMap 法线贴图
法线贴图+纹理贴图(细节明显) 纹理贴图 法线贴图 法线贴图 存储法线的一张贴图,归一化的法线的 xyz 的值被映射成为对应的 RGB 值.归一化的法线值为[-1,1],RGB的每一个分量为无符号的8 ...
- 数据结构-B+树
B+ 树是一种树数据结构,是一个n叉排序树,每个节点通常有多个孩子,一棵B+树包含根节点.内部节点和叶子节点.根节点可能是一个叶子节点,也可能是一个包含两个或两个以上孩子节点的节点. B+ 树通常用于 ...
- fzu 2113 数位dp
#include<stdio.h> #include<string.h> #define N 20 #define ll __int64 ll dp[N][N];//最多记忆4 ...
- Thinkphp5.0 的Db操作
Thinkphp5.0 的Db操作 连接操作: <?php namespace app\index\controller; use think\Controller; use think\Db; ...
- MeepoPS基本使用方法
MeepoPS基本使用 MeepoPS是Meepo PHP Socket的缩写. 旨在提供高效稳定的由纯PHP开发的多进程SocketService. MeepoPS可以轻松构建在线实时聊天, 即时游 ...
- HDU 5876 补图 单源 最短路
---恢复内容开始--- Sparse Graph Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (J ...