【Java基础】 序列化和反序列化

简介: Java中的序列化(Serialization)和反序列化(Deserialization)是将对象和字节流之间进行相互转换的过程。这两个过程用于保存对象的状态并能够在需要时恢复这些状态。

Java中的序列化(Serialization)和反序列化(Deserialization)是将对象和字节流之间进

行相互转换的过程。这两个过程用于保存对象的状态并能够在需要时恢复这些状态。

一、理解序列化和反序列化

概念

序列化:序列化是将对象的状态转换为字节流的过程,以便可以将该对象保存到文件、数据库,或通过网络进行传输。序列化使得对象的生命周期可以超越JVM的运行时间,并且可以在不同的机器之间传输。

反序列化:反序列化是将字节流恢复为对象的过程。通过反序列化,可以从序列化的字节流中重新创建对象的实例。

Java序列化的优点

1. 对象持久化:

可以将对象的状态保存到文件、数据库等持久化存储中,以便在以后可以恢复和使用。

2. 对象传输:

在分布式系统中,可以通过网络传输对象。序列化将对象转换为字节流,使得对象可以通过网络传输到其他Java虚拟机上。

3. 缓存:

将对象序列化后保存在缓存中,以提高系统性能。反序列化时可以快速恢复对象,而不需要重新创建。

4. 深拷贝:

通过序列化和反序列化可以实现对象的深拷贝。将对象序列化后再反序列化,得到的是一个全新的对象,所有引用类型的成员变量也会被拷贝。

5. 会话管理:

在Web应用中,可以将用户会话信息序列化到文件或数据库中,以便在服务器重启后恢复用户会话。

二、序列化的实现原理

1.  实现 Serializable 接口:

一个类必须实现  java.io.Serializable 接口才能使其对象序列化。

该接口是一个标记接口(没有方法),其目的是告诉JVM该类的对象可以被序列化。

2.  ObjectOutputStream:

使用  ObjectOutputStream 类来将对象写入到输出流中。

调用   writeObject(Object obj) 方法将对象转换为字节流。

3.  serialVersionUID:

用于版本控制。确保在反序列化时,加载的类与序列化的类是兼容的。

如果没有定义  serialVersionUID ,Java会根据类的细节自动生成一个,但是这个自动生成的ID在类的定义发生变化时可能会变化,从而导致反序列化失败。

建议显式声明  serialVersionUID 例如:

private static final long serialVersionUID = 1L;

三、API 介绍


API是Java平台提供的一系列接口和类,用于支持对象的序列化和反序列化。

基本概念与用法


Serializable接口为实现序列化的类提供了标记。任何需要被序列化的类都必须实现这个接口。

ObjectOutputStream类这是用于序列化的主要类。它提供了writeObject方法,能够将对象写入输出流,从而完成序列化过程。

ObjectInputStream类:这个类用于从输入流中读取字节序列并将其反序列化为对象。它通过readObject方法实现这一功能。

自定义序列化

如果需要自定义序列化过程,可以在类中定义 writeObject readObject 方法,

这时候序列化与反序列化会调用这些方法而不是默认方法,从而允许开发者对序列化过程进行更精细的控制。

private void writeObject(ObjectOutputStream out) throws IOException {
    // 自定义序列化逻辑
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    // 自定义反序列化逻辑
}

transient关键字

在Java中,transient关键字用于标识某个类的字段不需要进行序列化。具体来说,使用transient修饰的字段在对象序列化时不会被保存到字节流中,从而也不会在反序列化时恢复该字段的值。

transient 关键字的使用场景

敏感数据:

对于包含敏感信息的字段,如密码、信用卡信息等,使用transient关键字可以避免在序列化过程中泄露这些信息。

冗余数据:

如果某些字段的值是可以计算或重新生成的,可以将这些字段标记为transient以减少序列化数据的大小。


非持久化状态:

某些字段只用于临时计算或逻辑控制,不需要被序列化和持久化。例如,缓存数据、线程相关状态等。

transient 关键字的使用

import java.io.*;
class User implements Serializable {
    private static final long serialVersionUID = 1L;
    String username;
    transient String password; // 不会被序列化
    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
}

四、实现Java序列化的三种方法


使用Serializable接口:这是Java提供的标准序列化机制。要实现对象的序列化,需要让对象所属的类实现Serializable接口,并使用ObjectOutputStream类的writeObject方法将对象写入到输出流中。反序列化时,可以使用ObjectInputStream类的readObject方法从输入流中读取字节序列并将其反序列化为对象。

使用Externalizable接口:与Serializable接口相比,Externalizable接口提供了更精细的控制,允许开发者自定义序列化和反序列化的过程。要实现对象的序列化,需要让对象所属的类实现Externalizable接口,并实现writeExternal方法和readExternal方法。这两个方法分别用于将对象转换为字节流以及从字节流中恢复对象。

使用JSON序列化:JSON是一种轻量级的数据交换格式,可以方便地将Java对象转换为JSON字符串,并将JSON字符串转换回Java对象。在Java中,可以使用第三方库如Jackson、Gson等来实现JSON序列化。通过这些库提供的API,可以将Java对象转换为JSON字符串,并将JSON字符串转换回Java对象。

五、代码示例

1. 序列化示例

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
// 定义一个实现Serializable接口的Employee类,用于对象的序列化和反序列化
class Employee implements Serializable {
    // serialVersionUID用于版本控制,确保序列化和反序列化过程中类的兼容性
    private static final long serialVersionUID = 1L;
    // 员工的姓名
    String name;
    // 员工的ID
    int id;
    // 构造函数,初始化name和id字段
    public Employee(String name, int id) {
        this.name = name;
        this.id = id;
    }
}
// 序列化示例类
public class SerializeExample {
    public static void main(String[] args) {
        // 创建一个Employee对象
        Employee emp = new Employee("John Doe", 12345);
        // 使用try-with-resources语句,确保在try语句结束后自动关闭资源
        try (
            // 创建文件输出流,指定输出文件为"employee.ser"
            FileOutputStream fileOut = new FileOutputStream("employee.ser");
           
            // 创建对象输出流,将对象写入到文件输出流中
            ObjectOutputStream out = new ObjectOutputStream(fileOut)
        ) {
            // 将Employee对象写入输出流,即序列化对象
            out.writeObject(emp);
           
            // 打印提示信息,表示序列化数据已保存到指定文件中
            System.out.println("Serialized data is saved in employee.ser");
        } catch (Exception e) {
            // 捕获并处理异常,打印堆栈跟踪信息
            e.printStackTrace();
        }
    }
}

2. 反序列化示例

import java.io.FileInputStream;
import java.io.ObjectInputStream;
// 反序列化示例类
public class DeserializeExample {
    public static void main(String[] args) {
        Employee emp = null; // 声明一个Employee对象变量,并初始化为null,用于存储反序列化后的对象
        try (
            // 使用try-with-resources语句,确保在try语句结束后自动关闭资源
            FileInputStream fileIn = new FileInputStream("employee.ser"); // 创建文件输入流,指定输入文件为"employee.ser"
            ObjectInputStream in = new ObjectInputStream(fileIn) // 创建对象输入流,从文件输入流中读取对象
        ) {
            emp = (Employee) in.readObject(); // 从输入流中读取对象,即反序列化对象
        } catch (Exception e) {
            // 捕获并处理异常,打印堆栈跟踪信息
            e.printStackTrace();
        }
        // 如果emp不为null,则表示反序列化成功
        if (emp != null) {
            // 打印提示信息,表示反序列化成功
            System.out.println("Deserialized Employee...");
           
            // 打印反序列化后的员工姓名
            System.out.println("Name: " + emp.name);
           
            // 打印反序列化后的员工ID
            System.out.println("ID: " + emp.id);
        }
    }
}

目录
相关文章
|
8天前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
14天前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
49 5
|
15天前
|
存储 缓存 安全
🌟Java零基础:深入解析Java序列化机制
【10月更文挑战第20天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
21 3
|
18天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
1月前
|
存储 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第9天】在Java的世界里,对象序列化是连接数据持久化与网络通信的桥梁。本文将深入探讨Java对象序列化的机制、实践方法及反序列化过程,通过代码示例揭示其背后的原理。从基础概念到高级应用,我们将一步步揭开序列化技术的神秘面纱,让读者能够掌握这一强大工具,以应对数据存储和传输的挑战。
|
1月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。
|
1月前
|
消息中间件 存储 Java
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
41 3
|
18天前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
15 0
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
3月前
|
存储 开发框架 .NET
解锁SqlSugar新境界:利用Serialize.Linq实现Lambda表达式灵活序列化与反序列化,赋能动态数据查询新高度!
【8月更文挑战第3天】随着软件开发复杂度提升,数据查询的灵活性变得至关重要。SqlSugar作为一款轻量级、高性能的.NET ORM框架,简化了数据库操作。但在需要跨服务共享查询逻辑时,直接传递Lambda表达式不可行。这时,Serialize.Linq库大显身手,能将Linq表达式序列化为字符串,实现在不同服务间传输查询逻辑。结合使用SqlSugar和Serialize.Linq,不仅能够保持代码清晰,还能实现复杂的动态查询逻辑,极大地增强了应用程序的灵活性和可扩展性。
135 2