Java的序列化和反序列化机制

简介: Java的序列化和反序列化机制讲解,通俗易懂

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

Java序列化就是指把Java对象转换为字节序列的过程

Java反序列化就是指把**字节序列**恢复为**Java对象**的过程。

二、为什么要把一个对象序列化

正常情况下,Java new出的对象,是保存在内存当中的,是不能持久化保存的,也不能直接在网络中传输,如何解决呢?就是把Java对象转换为byte字节数据,以字节的方式去实现持久化保存和网络传输。而反序列化,就是把须列化后的数据,重新恢复成内存中的Java对象。

总之,序列化,就是对一个Java对象的保存和重建的过程。

三、Java实现序列化的过程

为了让一个Java对象能序列化,我们需要为这个Java对象实现Serializable接口,像下面这样,这个方法和普通的Bean来说,多继承了这个接口,这个接口没有实现实现任何方法,它是为什么告诉编译器,这个接口可以序列化。


@Data
public class User implements Serializable {


    private String name;

    private int age;

    private String  sex;

    private String phone;


}

这个类可以序列化了,但如何序列化让它能本地存储呢?执行下面的write方法,将会在D盘根目录下创建User类的序列化文件,执行read方法可以把序列化文件转变成对象。

public class Client {

    @Test
    public void write() throws Exception{
        User user = new User();
        user.setAge(15);
        user.setName("张三");
        user.setPhone("123");
        FileOutputStream fileOutputStream = new FileOutputStream("D://out.txt");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(user);

    }

    @Test
    public void read() throws Exception{
        FileInputStream fileInputStream = new FileInputStream("D://out.txt");
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        User o = (User)objectInputStream.readObject();
        System.out.println(o.toString());
    }

}

read方法运行结果,序列化出来的对象,拥有序列化之前对象的值。

在这里插入图片描述

四、不能被序列化的对象

Java对象中,如果一个字段被transient修饰,或者这个字段是static静态字段,这个类将不会被序列化,意味着,这个对象被序列化后,再次反序列化成Java对象后,对于的字段值为null。
在这里插入图片描述

五、序列号的作用

我们的类是不断的变动的,我们把一个对象序列化到本地文件后,有一天,这个对象的类发送了改变,我们用这个改变后的类接收序号化文件,会发生什么?把name和age注释掉,然后去反序列化。

public class User implements Serializable {


//     private String name;
//
//    transient private int age;

    private String  sex;

    private String phone;

    
}

public class Client {

    @Test
    public void write() throws Exception{
        User user = new User();
//        user.setAge(15);
//        user.setName("张三");
        user.setPhone("123");
        FileOutputStream fileOutputStream = new FileOutputStream("D://out.txt");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(user);

    }

    @Test
    public void read() throws Exception{
        FileInputStream fileInputStream = new FileInputStream("D://out.txt");
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        User o = (User)objectInputStream.readObject();
        System.out.println(o.toString());
    }

}



结果就是

java.io.InvalidClassException: com.example.service.demo01.User; local class incompatible: stream classdesc serialVersionUID = -118799779803260725, local class serialVersionUID = 1681826866445576943

这个报错是什么意思?是这个类和序列化文件里的类的序列号不一样,无法反序列化。
这里出现了一个问题,什么是序列号?

序列号是一个长整型的数据,一个类的序列号,是根据这个类的成员变量计算出来,如果成员变量发生改变,序列号也会发生改变,只有序列化文件的序列号和类的序列号相同,才能反序列化成功。
所以这个报错就很容易理解了,在改动前,类有三个变量,序列号的值假设是3,序列化的文件也是3,删除一个变量后,只剩两个变量,假设序列号是2,这样和序列化文件的序列号就不一样了,所以无法反序列化。

有时候,我们希望,即使类发生了改变,也能反序列化成功,比如之前有现在只剩3个字段,序列化的文件有4个字段,我们只序列化现在的类有的字段,那该怎么做?
我们可以手动为一个类设置序列号,像这样:
在这里插入图片描述
这样,即使类发生了改变,但是序列号我们已经手动写死了,之后类再怎么发生变化,反序列化也不会报错,只会序列那化些还能对应上的值。

相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
77 2
|
1月前
|
Java 编译器
探索Java中的异常处理机制
【10月更文挑战第35天】在Java的世界中,异常是程序运行过程中不可避免的一部分。本文将通过通俗易懂的语言和生动的比喻,带你了解Java中的异常处理机制,包括异常的类型、如何捕获和处理异常,以及如何在代码中有效地利用异常处理来提升程序的健壮性。让我们一起走进Java的异常世界,学习如何优雅地面对和解决问题吧!
|
22天前
|
Java 程序员
深入理解Java异常处理机制
Java的异常处理是编程中的一块基石,它不仅保障了代码的健壮性,还提升了程序的可读性和可维护性。本文将深入浅出地探讨Java异常处理的核心概念、分类、处理策略以及最佳实践,旨在帮助读者建立正确的异常处理观念,提升编程效率和质量。
107 1
|
23天前
|
Java 开发者 UED
深入探索Java中的异常处理机制##
本文将带你深入了解Java语言中的异常处理机制,包括异常的分类、异常的捕获与处理、自定义异常的创建以及最佳实践。通过具体实例和代码演示,帮助你更好地理解和运用Java中的异常处理,提高程序的健壮性和可维护性。 ##
47 2
|
23天前
|
Java 开发者
Java中的异常处理机制深度剖析####
本文深入探讨了Java语言中异常处理的重要性、核心机制及其在实际编程中的应用策略,旨在帮助开发者更有效地编写健壮的代码。通过实例分析,揭示了try-catch-finally结构的最佳实践,以及如何利用自定义异常提升程序的可读性和维护性。此外,还简要介绍了Java 7引入的多异常捕获特性,为读者提供了一个全面而实用的异常处理指南。 ####
48 2
|
26天前
|
Java 程序员 UED
深入理解Java中的异常处理机制
本文旨在揭示Java异常处理的奥秘,从基础概念到高级应用,逐步引导读者掌握如何优雅地管理程序中的错误。我们将探讨异常类型、捕获流程,以及如何在代码中有效利用try-catch语句。通过实例分析,我们将展示异常处理在提升代码质量方面的关键作用。
34 3
|
26天前
|
Java 数据库连接 开发者
Java中的异常处理机制:深入解析与最佳实践####
本文旨在为Java开发者提供一份关于异常处理机制的全面指南,从基础概念到高级技巧,涵盖try-catch结构、自定义异常、异常链分析以及最佳实践策略。不同于传统的摘要概述,本文将以一个实际项目案例为线索,逐步揭示如何高效地管理运行时错误,提升代码的健壮性和可维护性。通过对比常见误区与优化方案,读者将获得编写更加健壮Java应用程序的实用知识。 --- ####
|
27天前
|
运维 Java 编译器
Java 异常处理:机制、策略与最佳实践
Java异常处理是确保程序稳定运行的关键。本文介绍Java异常处理的机制,包括异常类层次结构、try-catch-finally语句的使用,并探讨常见策略及最佳实践,帮助开发者有效管理错误和异常情况。
86 4
|
26天前
|
开发框架 安全 Java
Java 反射机制:动态编程的强大利器
Java反射机制允许程序在运行时检查类、接口、字段和方法的信息,并能操作对象。它提供了一种动态编程的方式,使得代码更加灵活,能够适应未知的或变化的需求,是开发框架和库的重要工具。
41 2
|
1月前
|
Java
深入探讨Java中的中断机制:INTERRUPTED和ISINTERRUPTED方法详解
在Java多线程编程中,中断机制是协调线程行为的重要手段。了解和正确使用中断机制对于编写高效、可靠的并发程序至关重要。本文将深入探讨Java中的`Thread.interrupted()`和`Thread.isInterrupted()`方法的区别及其应用场景。
37 4