Java序列化流和反序列化流

news2024/9/22 7:40:35

     序列化流:
        序列化:将一个对象转换成网络中传输的流
            对象输出流:ObjectOutputStream
        反序列化:将网络中传输的流还原成一个对象
            对象输入流:ObjectInputStream

 一个类对象将来要想被序列化,必须要实现Serializable接口,这个接口中没有任何的方法和常量,称为标记接口。

InvalidClassException异常
我们在写完对象后,又修改了类中的内容,又重新写入,再读取的还原对象的时候,报错了InvalidClassException异常
这是因为修改后的UID发生了改变,序列化的对象UID:stream classdesc serialVersionUID = -7948663535168613063, 本地修改后的UID: local class serialVersionUID = 4202380653329948443,  因为没有固定UID,所以每次修改完,UID都会变
解决方案:在Students类里将serialVersionUID写固定,将来谁都不能改,就不会出现修改后错误,不用手写,自动生成即可。
第一步:直接点击异常类

第二步:复制UID

第三步:将复制的UID写入Students类中

第四步:需要重新运行一次程序,只调用write方法,等于将固定UID写入文本中

第五步:修改变量,或者增加其他变量

第六步:修改变量后,只调用read方法,程序也不会报错

总结:序列化对象,要一边修改,一边写入一边读,就不会出现UID不一样的错误

序列化和反序列化使用参考源码:

Students类:
import java.io.Serial;
import java.io.Serializable;

//TODO: 实现序列化需要实现一个Serializable 标记接口(所谓标记接口就是没有任何成员方法和变量,就只是作标记)
//TODO: transient修饰成员变量可以防止被序列化
//    我们在写完对象后,又修改了类中的内容,再读取的还原对象的时候,报错了InvalidClassException

//        stream classdesc serialVersionUID = 2442942279365203766,每次写完UID都会变
//        local class serialVersionUID = 2935475373948736279
//
//  TODO:       解决方案:将serialVersionUID写固定,将来谁都不能改,自动生成即可。
//
//TODO:    若成员不想被序列化存储,使用java提供一个关键字进行修饰 transient
public class Students implements Serializable {
    @Serial
    private static final long serialVersionUID = -4333316296251054416L;
    private String name;
    private int age;
    private String address;
    private  int caiFu;

    public Students() {
    }

    public Students(String name, int age, String address,int caiFu) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public int getCaiFu() {
        return caiFu;
    }

    public void setCaiFu(int caiFu) {
        this.caiFu = caiFu;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Students{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", caiFu=" + caiFu +
                '}';
    }
}
测试类:
import java.io.*;
//TODO:关于序列化流,正常写入文本的对象是什么内容,读出来的也就是什么内容,如果临时修改成员方法,并未及时写入原来的文本中
//TODO:这时候再次读就会报错,原因是每次修改后的序列化UID都会发生改变,所以要想正常读出来,则必须固定UID,但是读出来的新的参数的值是默认值,
//TODO:因为没有立即将新内容写入进去。另外被transient修饰的成员变量不会被序列化,就是普通变量,不会对序列化产生影响

//TODO:总结:序列化对象,要一边修改,一边写入一边读,就不会出现UID不一样的错误
public class XuLeiHuaTest {
    public static void main(String[] args) {
//        write();
        read();


    }
    public static void write(){
        //序列化流(输出流)
        ObjectOutputStream ous=null;
        try {
            ous = new ObjectOutputStream(new FileOutputStream("src/main/java/day15_8_13/序列化流.txt"));
            Students s1 = new Students("小伟",18,"山东菏泽",12000);
           ous.writeObject(s1);//将对象序列化
            ous.flush();
        } catch (IOException e) {
           e.printStackTrace();
        }finally {
            try {
                //用完就释放资源
                ous.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void read(){
        //反序列化流(输入流)
        ObjectInputStream ois=null;
        try {
             ois = new ObjectInputStream(new FileInputStream("src/main/java/day15_8_13/序列化流.txt"));
            try {
                Object o = ois.readObject();
                //向下转型
                Students s1 = (Students) o;
                System.out.println(o);

            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

        } catch (IOException e) {
           e.printStackTrace();
        }finally {
            //用完释放资源
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2051162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

轻松上手MYSQL:MYSQL权限配置全攻略,打造安全的数据库环境

​ 🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》《MYSQL》 💪🏻 制定明确可量化的目标,坚持默默的做事。 ✨欢迎加入探索MYSQL权限配置之旅✨ 👋 大家好!文本学习和…

【秋招笔试】8.14联想(算法岗)-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 编程一对一辅导 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收…

Cortex-A7的GIC(全局中断控制器)使用方法(6):基于stm32MP135的IRQ初始化及处理流程分析

0 参考资料 STM32MP13xx参考手册.pdf(RM0475) ARM Generic Interrupt Controller Architecture version 2.0 - Architecture Specification.pdf 1 基于Cortex-A7的STM32MP135的IRQ初始化及处理流程分析 熟悉基于Cortex-M内核的stm32系列MCU的一定对中断…

RabbitMQ练习(Hello World)

1、RabbitMQ教程 《RabbitMQ Tutorials》https://www.rabbitmq.com/tutorials RabbitMQ是一个消息代理,它接受并转发消息。你可以将其想象成一个邮局:当你将需要邮寄的信件放入邮筒时,你可以确信邮递员最终会将邮件投递给你的收件人。在这个…

LDR6500-type-c 接口小封装PD取电协议芯片

LDR6500 Type-C PD取电芯片是一种基于Type-C接口的电源传输的协议芯片,它通过Type-C接口中的CC(Configuration Channel)线进行通信,协商电压、电流及供电方向。当设备连接时,双方会进行握手通信,以确定彼此…

在AMD GPU上进行Grok-1模型的推理

Inferencing with Grok-1 on AMD GPUs — ROCm Blogs 我们展示了如何通过利用ROCm软件平台,能在AMD MI300X GPU加速器上无缝运行xAI公司的Grok-1模型。 介绍 xAI公司在2023年11月发布了Grok-1模型,允许任何人使用、实验和基于它构建。Grok-1的不同之处…

Java学习Day29:查漏补缺

1.只创建对象不创建文件 2.过滤器 使用匿名内部类实现FileFilter接口,实现过滤; 递归实现遍历目录及子目录下的后缀为。txt文件 public class ioRee {public static void main(String[] args) throws IOException {File file new File("D:\\A&quo…

pywebview 入门

pywebview 入门 文档地址 地址 https://pywebview.flowrl.com/guide/ 一、pywebview 简介 1. 什么是 pywebview? pywebview 是一个轻量级的 python 库,旨在简化桌面应用程序的开发。它利用系统的 WebView 组件,使得开发人员可以使用现代 …

web过滤器,前后端同步异步交互,跨域问题,json等知识点

一.过滤器 (1)什么是过滤器 过滤器(Filter):是web服务器管理所有的web资源例如servlet,例如实现权限访问控制、过滤敏感词汇、压缩响应信息等。 (2)过滤器的作用 通过过滤器可以实现对服务器web资源的拦截,例如编码过滤器通过对web资源的过滤拦截可以实…

python-素数回文(赛氪OJ)

[题目描述] 现在给出一个素数,这个素数满足两点: 1、 只由 1∼9 组成,并且每个数只出现一次,如 13,23,1289 。 2、 位数从高到低为递减或递增,如 2459,87631 。 请你判断一下,这个素数的回文数是否为素数&a…

python之matplotlib (1 介绍及基本用法)

介绍 matplotlib是Python中的一个绘图库,它提供了一个类似于 MATLAB 的绘图系统。使用matplotlib你可以生成图表、直方图、功率谱、条形图、错误图、散点图等。matplotlib广泛用于数据可视化领域,是 Python 中最著名的绘图库之一。 同样matplotlib的安…

day23-测试自动化之Appium的滑动和拖拽事件、高级手势ActionChains、手机操作API

目录 一、滑动和拖拽事件 1.1.应用场景 1.2.swipe滑动事件 1.3.scroll滑动事件 1.4.drag_and_drop拖拽事件 1.5.滑动和拖拽事件的选择 二、高级手势ActionChains 2.1.应用场景 2.2.使用步骤 2.3.注意点 2.4.方法 1).手指轻敲操作 (掌握) 2).手势按下和抬起操作(掌握&#xff0…

【Win/Mac】InDesign 2024(id2024排版和设计软件)中文安装版

目录 一、软件概述 二、下载 三、主要特点 系统要求(Windows 系统) 一、最低系统要求 二、推荐系统要求 三、图形处理器要求 系统要求(Mac 系统) 一、最低系统要求 二、推荐系统要求 三、图形处理器要求 使用方法 一、…

【Keil5教程及技巧】耗时一周精心整理万字全网最全Keil5(MDK-ARM)功能详细介绍【建议收藏-细细品尝】

💌 所属专栏:【单片机开发软件技巧】 😀 作  者: 于晓超 🚀 个人简介:嵌入式工程师,专注嵌入式领域基础和实战分享 ,欢迎咨询! 💖 欢迎大家&#xff1…

缓存学习

缓存基本概念 概念 对于缓存,最普遍的理解是能让打开某些页面速度更快的工具。从技术角度来看,其本质上是因为缓存是基于内存建立的,而内存的读写速度相比之于硬盘快了xx倍,因此用内存来代替硬盘作为读写的介质当然能大大提高访…

亲测解决OneDrive: Proxy Authentication Error - 2606

这个问题由网络配置有误引起,解决方法是换网络或者关闭代理。 解决方法 换一个网络,比如手机wifi。如果开了代理可以把代理关了。 原版笔记 use vanilla network

RK3588——Linux系统烧录(以Firefly的Core-3588L为例)

Firefly的Core-3588L官网 1. 硬件连接 首先先用Type-C 一端数据线板子的OTG,另一端连接电脑的USB。 按住设备上的 RECOVERY (恢复)键并保持,连接电源,保持2秒左右,松开RECOVERY (恢复&#xff…

图模型训练

一、依赖安装 网址:pyg-team/pytorch_geometric: Graph Neural Network Library for PyTorch (github.com) 找到此处,点击here进入依赖安装界面 找到自己安装的torch版本并点击,,进入安装依赖 二、用库自带的数据集 代码&#x…

WCT系列(二):SyncTransactionQueue类详解

SyncTransactionQueue类: 接上一回的WindowContainerTransaction类讲解,上一篇博客根据TaskView.java中的updateTaskVisibility()方法分析了WindowContainerTransaction的功能及使用。本次继续上一篇的思路,主要拆解syncTransactionQueue类。…

【JUC】06-可重入锁

可重入锁:又称递归锁。在外层使用锁后,内层仍然可以使用,并不发生死锁,这样的锁就叫可重入锁。synchronized默认是一个可重入锁。 public class Demo01 {public synchronized void m1() {System.out.println(Thread.currentThrea…