JAVA的序列化和反序列化

1.谈到了序列化,那么我们必须要知道Java里面的序列化接口Serializable,相信大家打开这个类想查看源码时没结果发现这个接口竟然是空的。 想必这时候大家肯定是一脸懵逼, 一个空接口能实现什么功能呢,其实啊,这个Serializable接口的作用只有标识作用,即只是个标识接口。我们可以举个例子:

比如在课堂上有位学生遇到一个问题,于是举手向老师请教,这时老师帮他解答,那么这位学生的举手其实就是一个标识,自己解决不了问题请教老师帮忙解决。在Java中的这个Serializable接口其实是给jvm看的,通知jvm,我不对这个类做序列化了,你(jvm)帮我序列化就好了。

因此大家应该也明白了,Serializable接口就是Java提供用来进行高效率的异地共享实例对象的机制,实现这个接口即可,当然了,通过这个接口的注释也可以看出,它强烈建议我们自己定义一个serialversionUID,因为默认生成的serialversionUID对class极其敏感,在反序列化的时候很容易抛出InvalidClassException异常。

2.既然已经了解了这个序列化接口Serializable,那么就可以写序列化和反序列化了,所谓序列化就是指将对象转换为字节序列的过程,说白了,就是将序列化的对象存储成文件,直接看代码吧:

(1).首先就是转化的对象User类,代码如下:

typescript 复制代码
package com.example.main;

import java.io.Serializable;

//序列化的对象必须实现Serializable接口。
public class User implements Serializable{
    private String name;
    private String passWord;

    public User(String name, String passWord) {
        this.name = name;
        this.passWord = passWord;
    }

    public String getName() {
        return name;
    }

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

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    //此处之所以写toString()方法就是为了方便反序列化后能够在终端看到我们能看懂的字符串,而不是类名和哈希码。
    //因为每个Java类都默认继承了Object类,而且此处就算不写重写注解也无妨,但是为了便于阅读,还是建议写上好。
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", passWord='" + passWord + ''' +
                '}';
    }
}

(2).以下代码就是主方法执行序列化操作。

java 复制代码
package com.example.main;

import java.io.*;

public class Main {
    public static void main(String[] args) {
        //里面的./就是进入根目录。
        File file = new File("./name.txt");
        try {
            //如果文件路径不存在,那么就会创建一个。
            if (file.createNewFile()){
                System.out.println("创建成功");
            } else {
                System.out.println("文件已经创建");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //以下就是序列化过程,好好思考一下。
        User user = new User("jinxuan",21);
        try {
            //注意由于这里是要将对象写入文件,故应该使用objectOutputStream类。
            ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(file));
            stream.writeObject(user);
            stream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

但是我们通过查看name.txt文件就会发现里面都是乱码,这是因为我们在写入二进制数据而不是文件。

3.既然序列化完了,肯定就该反序列化了,反序列化就是序列化的反过程,将字节序列转换为JAVA对象,直接看代码如下:

代码如下:

java 复制代码
package com.example.main;

import java.io.*;

public class Main {
    public static void main(String[] args) {
        try {
            ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("./name.txt"));
            try {
                Object o = objectInputStream.readObject();
                User user = (User) o;
                System.out.println(user);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}

关于我们上面说到的SerialVersionUID ,这个可以的话必须要自己定义一个,而且尽量用Private 修饰,因为这个也没必要让外部类修改,之所以加上这个ID的目的就是为了在反序列化的时候操作系统会进行检测这个ID和序列化的时候的ID是否相同再进行反序列化,而JVM之所以会默认生成这样一个SerialVersionUID就是为了使其可以进行持久化,即有了标记才可以使得JVM允许其IO系统将其转换为字节数据。

相关推荐
泡泡以安8 分钟前
【Android逆向工程】第3章:Java 字节码与 Smali 语法基础
android·java·安卓逆向
毕设源码-朱学姐6 小时前
【开题答辩全过程】以 工厂能耗分析平台的设计与实现为例,包含答辩的问题和答案
java·vue.js
Spring AI学习7 小时前
Spring AI深度解析(9/50):可观测性与监控体系实战
java·人工智能·spring
java1234_小锋8 小时前
Spring IoC的实现机制是什么?
java·后端·spring
xqqxqxxq8 小时前
背单词软件技术笔记(V2.0扩展版)
java·笔记·python
消失的旧时光-19439 小时前
深入理解 Java 线程池(二):ThreadPoolExecutor 执行流程 + 运行状态 + ctl 原理全解析
java·开发语言
哈哈老师啊9 小时前
Springboot学生综合测评系统hxtne(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
java·数据库·spring boot
4311媒体网9 小时前
帝国cms调用文章内容 二开基本操作
java·开发语言·php
zwxu_9 小时前
Nginx NIO对比Java NIO
java·nginx·nio
可观测性用观测云10 小时前
Pyroscope Java 接入最佳实践
java