JAVA序列化和反序列化的底层实现原理解析

JAVA序列化和反序列化的底层实现原理解析

序列化与反序列化的概念

序列化

序列化是指将对象转换成可传输的格式(例如字节码),并且可以在将来重新创建出与原对象完全相同的副本。序列化操作可以在网络上传输对象,或者将对象存储到本地磁盘上。

反序列化

反序列化是指将序列化后的数据流还原为原来的对象的操作。也就是说,反序列化能够重新创建出一个和已序列化的对象完全相同的对象实例。

序列化原理

序列化的实现

Java 序列化由 ObjectOutput 和 ObjectOutputStream 两部分组成。

具体来讲,ObjectOutput 在写出对象前会先写出该对象的 MetaData,即对象类型信息和属性值信息,然后使用 java.io.Serializable 接口中的 writeObject 方法将实例对象写入输出流中。

而 ObjectOutputStream 实现了 ObjectOutput 接口,在序列化时也采用了写出 MetaData 和 对象信息的方式,但在写出 MetaData 时,对同一类型的 MetaData 只创建一个。在写出对象时,该对象的类型信息和之前已写出的类型信息进行匹配,如果找到相同的类型信息,就使用之前的 MetaData,否则就新创建一个 MetaData 并记录下来。

序列化的缺点

Java 序列化存在以下缺点:

  1. 序列化后的数据量大,序列化后的码流默认为二进制编码,体积较大,不利于网络传输。
  2. 序列化运行效率较低,可能会影响系统的性能。
  3. 序列化后的数据不便于人阅读。

反序列化原理

反序列化可以使用 ObjectInput 和 ObjectInputStream 实现。

ObjectInput 接口有一个 readObject 方法,可以将序列化后的数据流反序列化成相应的对象。与序列化类似,反序列化时也需先读取定制化的 MetaData,根据 MetaData 对读入的二进制序列化数据进行解码,并转化为实例对象。

同时,ObjectInputStream 可以通过 setAllowList() 方法设置反序列化时允许读取的类白名单或黑名单,以防止序列化漏洞。

示例说明

以下是一个序列化示例:

public class User implements Serializable {
    String name;
    int age;

    // 省略构造函数和 Getter/Setter 方法

    public static void main(String[] args) throws IOException {
        FileOutputStream fileOut = new FileOutputStream("user.ser");
        ObjectOutputStream out = new ObjectOutputStream(fileOut);

        User user = new User("Jack", 18);
        out.writeObject(user);

        out.close();
        fileOut.close();
    }
}

该代码片段将 User 对象序列化到 user.ser 中。

以下是一个反序列化示例:

public class User implements Serializable {
    String name;
    int age;

    // 省略构造函数和 Getter/Setter 方法

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fileIn = new FileInputStream("user.ser");
        ObjectInputStream in = new ObjectInputStream(fileIn);

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

        in.close();
        fileIn.close();
    }
}

该代码片段从 user.ser 中读出序列化后的 User 对象,并将其反序列化为 Java 对象实例。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JAVA序列化和反序列化的底层实现原理解析 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Hibernate中5个核心接口知识点整理

    当我们使用Hibernate进行数据库操作时,会经常接触到如下5个核心接口: SessionFactory Session Transaction Query Criteria 它们分别是什么,有何作用?下面我们进行详细讲解。 SessionFactory SessionFactory是Hibernate的核心接口之一,通常也是Hibernate启动过程中的…

    Java 2023年5月19日
    00
  • java高效实现大文件拷贝功能

    首先,针对java高效实现大文件拷贝功能,可以采用NIO(Non-blocking IO,非阻塞IO)的方式进行操作。 步骤一:使用Java NIO中的通道(Channel)创建文件输入输出流 在Java NIO中,Channel是用于连接Socket、File、Selector以及管道(Pipe)的一个全新的概念,它要比Java IO中的流(Stream)…

    Java 2023年5月20日
    00
  • IntelliJ IDEA 中必有得插件和配置

    让我来详细讲解一下“IntelliJ IDEA 中必有得插件和配置”的攻略。 为了让开发者能够更加高效地编写代码,IntelliJ IDEA 提供了丰富的插件和配置选项。以下是一些必备的插件和配置: 一、必备插件 1.1 Lombok Lombok 是一款能够帮助开发者消除 Java 代码中冗余、繁琐的语法的插件。它能够自动生成 getter、setter、…

    Java 2023年5月20日
    00
  • 带你了解Java数据结构和算法之无权无向图

    带你了解Java数据结构和算法之无权无向图 什么是无权无向图? 无权无向图是图论中的重要概念,它是由若干个点以及连接这些点的边组成的。其中,无权表示边之间没有权重的区别,无向表示边没有方向。 无权无向图的表示方式 在Java中,可以使用邻接表来表示无权无向图。邻接表是由若干个链表组成的数据结构,其中每个节点表示图中的一个顶点,节点的值表示该顶点的编号,节点的…

    Java 2023年5月19日
    00
  • Java遍历集合的三种方式

    当需要遍历一个集合中的元素时,Java提供了三种方式:for-each循环,for循环和迭代器。下面将分别介绍这三种方式以及它们的使用场景和示例代码。 使用for-each循环遍历集合 for-each循环也叫增强型for循环,在Java 5中引入。它可以帮助我们遍历集合中的元素,使得代码更加简洁易读。使用for-each循环遍历集合时,代码如下: List…

    Java 2023年5月26日
    00
  • 详解JNI到底是什么

    JNI全称为Java Native Interface,是Java语言与其他编程语言(如C、C++)进行交互的接口。JNI可以使Java程序通过调用本地(C、C++)编写的程序,实现高效的、与操作系统直接交互的功能。下面详细讲解JNI到底是什么,让你对JNI有更深刻的理解和认识。 什么是JNI? JNI是Java的一部分,是Java语言本身提供的一个开发工具…

    Java 2023年5月26日
    00
  • 详解netty中的frame解码器

    下面是详解netty中的frame解码器的攻略: 1. 前言 Netty是一款高性能、可扩展性强、可维护性好的Java 网络编程框架。其中,数据包的传输是网络编程中的重要环节。在数据包传输过程中,需要对数据包进行解码操作,将二进制流转化为对应的Java对象。 Netty中基于框架机制实现了多个解码器,其中frame解码器是Netty中比较常用的解码器之一。本…

    Java 2023年5月20日
    00
  • SpringMVC实现注解式权限验证的实例

    针对“SpringMVC实现注解式权限验证的实例”的完整攻略,我们可以按照以下步骤进行: 1. 添加依赖 在 pom.xml 中添加以下依赖: <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</a…

    Java 2023年6月16日
    00
合作推广
合作推广
分享本页
返回顶部