如何使用Externalizable接口自定义Java中的序列化
Java序列化过程的缺点
我们都知道如何使用Serializable接口序列化/反序列化一个对象,并且如何使用writeObject
和readObject方法自定义序列化过程。
但是这些自定义还不够,因为JVM可以完全控制序列化过程,而这些自定义逻辑只是默认序列化过程的补充。我们仍然必须通过调用ObjectOutputStream.defaultWriteObject()和ObjectInputStream.defaultReadObject()from writeObject和readObject方法使用默认的序列化逻辑。如果我们不调用这些默认方法,我们的对象将不会被序列化/反序列化。
默认序列化过程是完全递归的。因此,每当我们尝试序列化一个对象时,序列化过程会尝试使用我们的类(除了static和transient字段)序列化所有字段(原语和引用),这使得序列化过程非常缓慢。
现在,假设我们有一个包含许多字段的对象,由于某种原因我们不想序列化(这些字段将始终分配默认值)。使用默认的序列化过程,我们必须使所有这些字段都是瞬态的,但它仍然不会有效,因为会进行大量检查以查看字段是否是瞬态的。
正如我们所看到的,使用默认序列化过程有许多缺点,例如:
1.序列化的自定义是不够的,因为JVM可以完全控制序列化过程,而我们的自定义逻辑只是默认序列化过程的补充。
2.默认序列化过程是完全递归和缓慢的。
3.为了不对字段进行序列化,我们必须将其声明为瞬态,并且许多瞬态字段将再次使该过程变慢。
4.我们无法控制字段的序列化和反序列化方式。默认序列化过程在创建对象时不会调用构造函数,因此它无法调用构造函数提供的初始化逻辑。
什么是外化和可外化接口?
如上所述,默认的Java序列化效率不高。我们可以通过使用Externalizable接口而不是Serializable接口来解决其中的一些问题。
我们可以通过实现写自己的序列化逻辑外部化的界面和重写它的方法writeExternal()和readExternal()。但是使用这种方法,我们不会从JVM获得任何类型的默认序列化逻辑,我们需要提供完整的序列化和反序列化逻辑。
因此,非常有必要仔细编码和测试这些方法,因为它可能会破坏序列化过程。但是,如果正确实施,外部化过程与默认序列化过程相比非常快。
我们将使用下面的Employee类对象作为解释的示例:


序列化如何与Externalizable接口一起使用
正如我们上面看到的,在我们的例子Employee类,我们可以通过实现写自己的序列化逻辑外部化的界面和重写它的方法writeExternal()和readExternal()。
该对象可writeExternal通过调用DataOutput其原始值的writeObject 方法 或调用 ObjectOutput 对象,字符串和数组的方法来实现 保存其内容的方法 。
该对象可以readExternal通过调用DataInput基本类型的方法以及 readObject 对象,字符串和数组来实现 恢复其内容的方法 。该 readExternal方法必须以相同的顺序读取值,并使用与写入的相同类型 writeExternal。

要将对象序列化和反序列化为文件,我们需要按照Serializable示例中的相同步骤进行操作,这意味着调用ObjectOutputStream.writeObject()并ObjectInputStream.readObject()在以下代码中完成:

该Externalizable接口的子接口Serializable即Externalizable extends Serializable。因此,如果我们实现Externalizable接口并覆盖它writeExternal()和readExternal()方法,那么我们首先要优先考虑这些方法,而不是JVM提供的默认序列化机制。这些方法取代了自定义的实现writeObject和readObject方法。所以,如果我们还提供writeObject()和readObject(),那么他们将被忽略。
在序列化过程中,对每个要序列化的对象进行Externalizable 接口测试 。如果对象支持 Externalizable,writeExternal 则调用该 方法。如果对象不支持 Externalizable 并且实现
Serializable,则使用保存对象 ObjectOutputStream。
当一个 Externalizable 对象被重建,则使用公共无参数的构造创建的实例; 然后readExternal 调用该 方法。 Serializable通过从中读取对象来恢复它们 ObjectInputStream。
当一个 Externizable 对象被重建,通过使用公共的无参数构造的前创建的对象 readExternal 被调用的方法。如果不存在公共no-arg构造函数,则InvalidClassException 在运行时抛出a 。
使用 Externalizable,我们甚至可以序列化/反序列化瞬态变量,因此声明瞬态变为不必要。3.使用 Externalizable,如果需要,我们甚至可以序列化/反序列化静态变量。
一个 Externalizable实例可以通过指定一个替代对象 writeReplace 和 readResolve 在形成文件的方法 Serializable 接口。
Java 序列化也可用于深度克隆对象。Java克隆是Java社区中最值得商榷的主题,它确实有它的缺点,但它仍然是创建对象副本的最流行和最简单的方法,直到该对象完全填充Java克隆的强制条件。
有关于JAVA的问题可私信我交流!
如何使用Externalizable接口自定义Java中的序列化的更多相关文章
- Java中如何序列化一个对象(转)
转自:http://blog.csdn.net/chx10051413/article/details/40784667 http://www.cnblogs.com/baoendemao/p/380 ...
- Java中的序列化Serialable
Java中的序列化Serialable https://blog.csdn.net/caomiao2006/article/details/51588838
- Java中实现序列化的两种方式 Serializable 接口和 Externalizable接口
对象的序列化就是将对象写入输出流中. 反序列化就是从输入流中将对象读取出来. 用来实现序列化的类都在java.io包中,我们常用的类或接口有: ObjectOutputStream:提供序列化对象并把 ...
- 并发王者课-铂金1:探本溯源-为何说Lock接口是Java中锁的基础
欢迎来到<并发王者课>,本文是该系列文章中的第14篇. 在黄金系列中,我们介绍了并发中一些问题,比如死锁.活锁.线程饥饿等问题.在并发编程中,这些问题无疑都是需要解决的.所以,在铂金系列文 ...
- K:java中的序列化与反序列化
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?以下内容将围绕这些问题进行展开讨论. Java序列化与反序列化 简单来说Java序列化是指把Java对象转 ...
- 在Java中进行序列化和反序列化
对象序列化的目标是将对象保存在磁盘中,或者允许在网络中直接传输对象. 对象序列化允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久保存在磁盘上或者通过网络将这种二进制流传输 ...
- java中的序列化问题
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,将数据分解成字节流,以便存储在文件中或在网络上传输.可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间.序列化是 ...
- Java中的序列化与反序列化
序列化定义 将对象转换为字节流保存起来,并在以后还原这个对象,这种机制叫做对象序列化. 将一个对象保存到永久存储设备上称为持久化. 一个对象要想能够实现序列化,必须实现java.io.Serializ ...
- java中的序列化和反序列化
package cn.zhou; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.Fil ...
随机推荐
- Spring Boot跨域解决方案
一.什么是跨域 为保证浏览器的安全,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源,这称之为同源策略,如果一个请求地址里的协议.域名.端口号都相同,就属于同源.依据浏览器同源策略,非同源脚 ...
- Spring Cloud同步场景分布式事务怎样做?试试Seata
一.概述 在微服务架构下,虽然我们会尽量避免分布式事务,但是只要业务复杂的情况下这是一个绕不开的问题,如何保证业务数据一致性呢?本文主要介绍同步场景下使用Seata的AT模式来解决一致性问题. Sea ...
- [vue] vue服务端渲染nuxt.js
初始化 使用脚手架工具 create-nuxt-app 快速创建 npx create-nuxt-app <项目名> npx create-nuxt-app 执行一些选择 在集成的服务器端 ...
- Weblogic任意文件上传漏洞(CVE-2018-2894)复现
使用docker搭建漏洞测试环境 micr067@test:~/vulhub/weblogic/CVE-2018-2894$ sudo docker-compose build weblogic us ...
- Maven 梳理 -多模块 vs 继承
Maven提高篇系列之(一)——多模块 vs 继承 这是一个Maven提高篇的系列,包含有以下文章: Maven提高篇系列之(一)——多模块 vs 继承 Maven提高篇系列之(二)——配置Plu ...
- JavaScript总结(一)
一.JavaScript 简介 1.1 .什么是 JavaScript? JavaScript 的简称:JS. JavaScript 是一个脚本.(不需要经过编译器编译的语言就叫做脚本) JavaSc ...
- RecyclerView实现Gallery画廊效果
使用RecyclerView实现一个画廊效果,主要是使用support库中最新加入的PagerSnapHelper类,通过计算滑动偏移来计算scale的值. 基本实现 首先需要为RecyclerVie ...
- thymeleaf 日期时间格式处理
一.#dates.format()用来格式化日期时间 ${#dates.format(date, 'dd/MMM/yyyy HH:mm')} ${#dates.arrayFormat(datesArr ...
- 【爬虫小程序:爬取斗鱼所有房间信息】Xpath(多进程版)
# 本程序亲测有效,用于理解爬虫相关的基础知识,不足之处希望大家批评指正 import requests from lxml import etree from multiprocessing imp ...
- Python3编码解码url
python2和python3对于url的解码和编码 某天做爬虫时遇到一个post请求的参数是编码过的字符串如下,看不懂,初步判断可能是url编码 str = "%7B%22Shopping ...