原文地址:https://blog.csdn.net/xlgen157387/article/details/79840134

目录

一、基本概念

二、Java如何实现序列化和反序列化

三、相关注意事项

四、总结


序列化和反序列化作为Java里一个较为基础的知识点,大家心里也有那么几句要说的,但我相信很多小伙伴掌握的也就是那么几句而已,如果再深究问一下Java如何实现序列化和反序列化的,就可能不知所措了!遥记当年也被问了这一个问题,自信满满的说了一大堆,什么是序列化、什么是反序列化、什么场景的时候才会用到等,然后面试官说:那你能说一下序列化和反序列化底层是如何实现的吗?一脸懵逼,然后回家等通知!

一、基本概念

1、什么是序列化和反序列化

(1)Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程;

(2)序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了Java对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。

(3)反序列化:客户端从文件中或网络上获得序列化后的对象字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。

(4)本质上讲,序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态。

2、为什么需要序列化与反序列化

我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的!如何做到呢?这就需要Java序列化与反序列化了!换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。当我们明晰了为什么需要Java序列化和反序列化后,我们很自然地会想Java序列化的好处。总的来说可以归结为以下几点:

3、序列化算法一般会按步骤做如下事情

(1)将对象实例相关的类元数据输出。

(2)递归地输出类的超类描述直到不再有超类。

(3)类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。

(4)从上至下递归输出实例的数据

二、Java如何实现序列化和反序列化

1、JDK类库中序列化和反序列化API

2、实现序列化的要求

只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常!

3、实现Java对象序列化与反序列化的方法

假定一个User类,它的对象需要序列化,可以有如下三种方法:

ObjectOutputStream采用默认的序列化方式,对User对象的非transient的实例变量进行序列化。

ObjcetInputStream采用默认的反序列化方式,对对User对象的非transient的实例变量进行反序列化。

ObjectOutputStream调用User对象的writeObject(ObjectOutputStream out)的方法进行序列化。

ObjectInputStream会调用User对象的readObject(ObjectInputStream in)的方法进行反序列化。

ObjectOutputStream调用User对象的writeExternal(ObjectOutput out))的方法进行序列化。

ObjectInputStream会调用User对象的readExternal(ObjectInput in)的方法进行反序列化。

4、JDK类库中序列化的步骤

步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流:

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\object.out"));

步骤二:通过对象输出流的writeObject()方法写对象:

oos.writeObject(new User("xuliugen", "123456", "male"));

5、JDK类库中反序列化的步骤

步骤一:创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:

ObjectInputStream ois= new ObjectInputStream(new FileInputStream("object.out"));

步骤二:通过对象输出流的readObject()方法读取对象:

User user = (User) ois.readObject();

说明:为了正确读取数据,完成反序列化,必须保证向对象输出流写对象的顺序与从对象输入流中读对象的顺序一致。

6、序列化和反序列化的示例

为了更好地理解Java序列化与反序列化,举一个简单的示例如下:

public class SerialDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {//序列化FileOutputStream fos = new FileOutputStream("object.out");ObjectOutputStream oos = new ObjectOutputStream(fos);User user1 = new User("xuliugen", "123456", "male");oos.writeObject(user1);oos.flush();oos.close();//反序列化FileInputStream fis = new FileInputStream("object.out");ObjectInputStream ois = new ObjectInputStream(fis);User user2 = (User) ois.readObject();System.out.println(user2.getUserName()+ " " + user2.getPassword() + " " + user2.getSex());//反序列化的输出结果为:xuliugen 123456 male}
}public class User implements Serializable {private String userName;private String password;private String sex;//全参构造方法、get和set方法省略
}

object.out文件如下(使用UltraEdit打开):

注:上图中0000000h-000000c0h表示行号;0-f表示列;行后面的文字表示对这行16进制的解释;对上述字节码所表述的内容感兴趣的可以对照相关的资料,查阅一下每一个字符代表的含义,这里不在探讨!类似于我们Java代码编译之后的.class文件,每一个字符都代表一定的含义。序列化和反序列化的过程就是生成和解析上述字符的过程!

序列化图示:

反序列化图示:

三、相关注意事项

(1)序列化时,只对对象的状态进行保存,而不管对象的方法;

(2)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;

(3)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;

(4)并非所有的对象都可以序列化,至于为什么不可以,有很多原因了,比如安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行RMI传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的;比如资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现;

(5)声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据。

(6)序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。为它赋予明确的值。显式地定义serialVersionUID有两种用途:a. 在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;b. 在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

(7)Java有很多基础类已经实现了serializable接口,比如String,Vector等。但是也有一些没有实现serializable接口的;

(8)如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存!这是能用序列化解决深拷贝的重要原因;

四、总结

看到这里,可能已经让我们很满足了,毕竟已经知道了我们平时使用的序列化和反序列化是如何进行操作的,Java给我们提供了哪些接口可供使用,也比我们最初知道的简单的什么是序列化、反序列化以及作用多了很多!后续内容我们也会不断在讨论和更新!

Java基础—序列化底层原理相关推荐

  1. 【Java基础】HashMap原理详解

    [Java基础]HashMap原理详解 HashMap的实现 1. 数组 2.线性链表 3.红黑树 3.1概述 3.2性质 4.HashMap扩容死锁 5. BATJ一线大厂技术栈 HashMap的实 ...

  2. 程序员练级攻略(2018):前端基础和底层原理

    这个是我订阅 陈皓老师在极客上的专栏<左耳听风>,我整理出来是为了自己方便学习,同时也分享给你们一起学习,当然如果有兴趣,可以去订阅,为了避免广告嫌疑,我这就不多说了!以下第一人称是指陈皓 ...

  3. java原理教程,java基础之运行原理(一),java基础运行原理

    java基础之运行原理(一),java基础运行原理 java的核心配置:JDK JDK主要包括三个部分 1.Jre:java的运行环境 2.Java的工具:java的编译器(java.c.exe). ...

  4. Java集合—ArrayList底层原理

    原文作者:0 errors 0 warnings 原文地址:用大白话告诉你ArrayList的底层原理 目录 一.数据结构 二.线程安全性 三.继承关系 四.构造方法 五.add()方法 六.扩容机制 ...

  5. Java中序列化实现原理研究

    1.什么是序列化和反序列化 序列化 是指将Java对象保存为二进制字节码的过程. 反序列化 将二进制字节码重新转成Java对象的过程. 2.为什么序列化 我们知道,一般Java对象的生命周期比Java ...

  6. Java集合框架底层原理

    Java集合框架 Java集合框架 List集合 ArrayList底层实现原理 ArrayList数组扩容技术(数组拷贝) 扩容大小 查询和删除 集合中的泛型 LinkedList Vector 线 ...

  7. Java集合—HashMap底层原理

    原文链接:最通俗易懂搞定HashMap的底层原理 HashMap的底层原理面试必考题.为什么面试官如此青睐这道题?HashMap里面涉及了很多的知识点,可以比较全面考察面试者的基本功,想要拿到一个好o ...

  8. 关于Arrays.fill方法和Java赋值的底层原理

    目录 问题 原理 参考 问题 今天在写leetcode的时候看到了这样一个例子: StringBuilder[] a = new StringBuilder[5]; Arrays.fill(a, ne ...

  9. java基础、底层实现、面试

    目录 1.String.StringBufer.StringBuilder 1.1 String 1.2 StringBuffer.StringBuilder 1.3 Efficiency 2. In ...

最新文章

  1. Unity3D中的函数方法及解释
  2. python的sklearn机器学习SVM中的NuSVC运行报错:ValueError: b'specified nu is infeasible'
  3. dubbo启动顺序问题
  4. golang中的collection
  5. python 各层级目录下的import方法
  6. hyperworks2018安装教程
  7. getchar()函数的一些知识
  8. linux+后台运行+nohup,Linux后台运行命令集(、fg、bg、jobs、nohup、ctrl + z)
  9. jxl生成表格(合并单元格,字体,样式)
  10. 数字效率Evernote超效率数字笔记术
  11. golang switch_为什么程序员都不喜欢使用 switch ,而是大量的 if……else if ?
  12. 创建一个Flash站点的十大技巧
  13. php pdo fetchassoc,pdo执行fetch查询语句,出现500错误,请问应该怎么写
  14. 我来教你如何将自己的网站上传至服务器并通过域名进行访问
  15. php 图片消除锯齿,ps如何消除边缘锯齿
  16. 2023年全国最新二级建造师精选真题及答案44
  17. 毕设进度跟踪之开题报告
  18. PASCAL VOC 2012数据集及其增强版介绍
  19. cad计算机配置要求,cad对电脑硬件要求
  20. minio存储之纠删码(Erasure Code)

热门文章

  1. c# 过滤HTML代码 源代码,案例 下载
  2. 关于MFC共享DLL的模块状态切换 .
  3. Lucene排序以及自定义排序
  4. 使用python移动飞信模块发送短信
  5. javascript 学习之 数组式的对象
  6. 使用Emit反射建立运行时实体模型
  7. 如何诊断crs 安装时 root.sh 脚本执行错误
  8. Bootstrap 3 Typeahead
  9. node JS 微信开发
  10. 基于RTMP的实时流媒体的QoE分析