对象序列化流与反序列化流

举报
兰舟千帆 发表于 2022/07/21 18:46:15 2022/07/21
【摘要】 对象序列化流与反序列化流 什么是序列化与反序列化=java序列化,就是指吧java对象转换为字节序列的过程。而反序列自然就是将字节对象恢复为java对象。==这样做的意义在哪呢?对象进行序列化,会转换为字节流,这样在网络上传输,或者是进行保存为本地文件都是非常方便的。反序列很明显就是进行对象的重构。其实你可以和通信联系在一起。==网络上的文本,图片,视频,音频都是通过二进制进行传输的,我们...

对象序列化流与反序列化流

什么是序列化与反序列化

=java序列化,就是指吧java对象转换为字节序列的过程。而反序列自然就是将字节对象恢复为java对象。==

这样做的意义在哪呢?对象进行序列化,会转换为字节流,这样在网络上传输,或者是进行保存为本地文件都是非常方便的。反序列很明显就是进行对象的重构。

其实你可以和通信联系在一起。==网络上的文本,图片,视频,音频都是通过二进制进行传输的,我们的java所创建的对象在传输的时候也应该进行序列化,转换为字节流,然后通过网络,io传入,当我们的对象序列传输完成后,对方进行反序列化,就可以读取到数据内容。==

对象序列化流( ObjectOutputStream)

api对这个类有很多的说明,主要说明

public class ObjectOutputStreamextends OutputStreamimplements ObjectOutput, ObjectStreamConstants

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

看一下简单使用

首先我们需要一个对象类

package io_demo;

import java.io.Serializable;

public class Student implements Serializable {

    private String sid;
    private String name;
    int age;

    private String address;
    public Student()
    {

    }

    public Student(String sid, String name, int age, String address) {
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getName() {
        return name;
    }

    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;
    }
}

然后测试主类

package io_demo;

import java.io.*;

public class IoDemo_23 {
    //对象序列化流
//    构造方法
   // ObjectOutputStream(OutputStream out)
    public static void main(String args[]) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\java_doc\\src\\io_demo\\jgdabc.txt"));
        Student s = new Student("001","刘备",28,"汉中");
        oos.writeObject(s);//将对象序列化()
        oos.close();
    }
}

为什么Student需要实现Serializable,api有说明

只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。

为什么没有具体实现?
在这里插入图片描述
因为这个接口本身没有具体实现,==我们不要要实现什么,这个只是作为一个标识而已。==

对象反序列化流(.ObjectInputStream)

public class ObjectInputStream
extends InputStream
implements ObjectInput, ObjectStreamConstants

说明如下

ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。
ObjectOutputStream和ObjectInputStream可以分别为与FileOutputStream和FileInputStream一起使用的对象图提供持久性存储的应用程序。 ObjectInputStream用于恢复先前序列化的对象。 其他用途包括使用套接字流在主机之间传递对象,或者在远程通信系统中进行封送和解组参数和参数。

首先还是原来的Student对象类

package io_demo;

import java.io.Serializable;

public class Student implements Serializable {

    private String sid;
    private String name;
    int age;

    private String address;
    public Student()
    {

    }

    public Student(String sid, String name, int age, String address) {
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getName() {
        return name;
    }

    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;
    }
}

对的,==你虽然是从文件中读取,但是如果你不使用构建的对象的话。是绝对无法成功进行反序列化的。==

主要的测试代码

package io_demo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;

//反序列化ObiectreadObject() 进行读取来反序列化
public class IoDemo_24 {
    public static void main(String args[]) throws IOException, ClassNotFoundException {
        //实现对象反序列化流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\java_doc\\src\\io_demo\\jgdabc.txt"));
        Object o = ois.readObject();
        Student s = (Student)o;
        System.out.println(s.getName()+","+s.getAge());
        ois.close();


    }
}

在这里插入图片描述
这样感觉有时候很像加密与解密的样子。

如果在反序列话的时候原来对象类有修改?

我现在就修改一个属性。我让age属性权限有所变化,变为私有属性
在这里插入图片描述

**结果反序列化就报错了,为什么?你看报错 **

在这里插入图片描述
再清晰一点就是

local class incompatible: stream classdesc serialVersionUID = -8624680451455869930, local class serialVersionUID = 6474701452341618882

serialVersionUID是什么?(为什么修改对象类会反序列化失败?)

==serialVersionUID是序列化的时候会生成的一个的版本标识,。当我们对对象进行修改后,那么这个序列化的版本标识的值就会与之前的不一样了。这样会导致字节流的版本标识与本地的版本标识不一样,不一样就会反序列化失败。==

解决修改对象类修改反序列化失败的问题

==我们就自己定义一个常量。让这个版本标识符不再变化==
在这里插入图片描述
注意,一定是在对象类中,不是在测试类。

不想让某些属性被序列化?

这样就可以
在这里插入图片描述

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。