一定义以及相关概念

互联网的产生带来了机器间通讯的需求,而互联通讯的双方需要采用约定的协议,序列化和反序列化属于通讯协议的一部分。通讯协议往往采用分层模型,不同模型每层的功能定义以及颗粒度不同,例如: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序列化系列教程(上)的更多相关文章

  1. Java序列化系列教程(下)

    一引言 将 Java 对象序列化为二进制文件的 Java 序列化技术是 Java 系列技术中一个较为重要的技术点,在大部分情况下,开发人员只需要了解被序列化的类需要实现 Serializable 接口 ...

  2. 阿里 Java 手册系列教程:为啥强制子类、父类变量名不同?

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 父子类变量名相同会咋样? 为啥强制子类.父类变量名不同? ...

  3. 推介一个学习JAVA的系列教程-狗鱼IT教程

    介绍一个学JAVA的零基础学习JAVA的网站,推介一个学习JAVA的系列教程-狗鱼IT教程 下面是java的系教程: 1、[java教程]Java 教程 2、[java教程]Java 简介 3、[ja ...

  4. Java NIO系列教程(七) selector原理 Epoll版的Selector

    目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...

  5. Java NIO系列教程(三) Channel之Socket通道

    目录: <Java NIO系列教程(二) Channel> <Java NIO系列教程(三) Channel之Socket通道> 在<Java NIO系列教程(二) Ch ...

  6. Java NIO系列教程(二) Channel通道介绍及FileChannel详解

    目录: <Java NIO系列教程(二) Channel> <Java NIO系列教程(三) Channel之Socket通道> Channel是一个通道,可以通过它读取和写入 ...

  7. Java NIO系列教程(十一) Java NIO 与 IO

    Java NIO系列教程(十一) Java NIO与IO 当学习了 Java NIO 和 IO 的 API 后,一个问题马上涌入脑海: 我应该何时使用 IO,何时使用 NIO 呢?在本文中,我会尽量清 ...

  8. Java NIO系列教程(三-十二) Buffer

    原文链接     作者:Jakob Jenkov     译者:airu     校对:丁一 Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到 ...

  9. Java NIO系列教程(八)JDK AIO编程

    目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...

随机推荐

  1. ORM之单表增删改查

    ORM之单表增删改查 在函数前,先导入要操作的数据库表模块,model from model所在的路径文件夹 import model   在views文件中,加的路径: #就一个app01功能的文件 ...

  2. 杭电 4883 TIANKENG’s restaurant (求饭店最少需要座椅)

    Description TIANKENG manages a restaurant after graduating from ZCMU, and tens of thousands of custo ...

  3. 每周一赛(E题,广搜求方案)

    Description In this problem, you are given an integer number s. You can transform any integer number ...

  4. poj 3253 Fence Repair (优先队列,哈弗曼)

    题目链接:http://poj.org/problem?id=3253 题意:给出n块木板的长度L1,L2...Ln,求在一块总长为这个木板和的大木板中如何切割出这n块木板花费最少,花费就是将木板切割 ...

  5. 开发调式时生成dump文件

    开发调式时,对程序生成dump文件:1:需要生成的时机,加Thread.sleep(600*1000).2:打开jvisualvm找到该程序进程号.3:jmap.

  6. Centos下安装X Window+GNOME Desktop+FreeNX

    FreeNX是近年来继VNC之后新出现的远程控制解决方案,基本原理是将XWindows的信号压缩后传输到远程客户端显示,而VNC是直接截取 屏幕图像处理传输.这样,在同样的传输信道条件下,FreeNX ...

  7. Reactor Cooling(无源汇有上下界网络流)

    194. Reactor Cooling time limit per test: 0.5 sec. memory limit per test: 65536 KB input: standard o ...

  8. Linux下汇编语言学习笔记5 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  9. Codeforces 645B Mischievous Mess Makers【逆序数】

    题目链接: http://codeforces.com/problemset/problem/645/B 题意: 给定步数和排列,每步可以交换两个数,问最后逆序数最多是多少对? 分析: 看例子就能看出 ...

  10. 【SQL Server 学习系列】-- 随机生成日期时间的SQL脚本

    DECLARE @dt1 DATETIME,@dt2 DATETIME,@a BIGINT,@b BIGINT SET @dt1='2010-01-01'--开始日期 SET @dt2='2010-0 ...