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系统将其转换为字节数据。

相关推荐
腻害兔17 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社18 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
萧瑟余晖19 小时前
JDK 26 新特性详解
java·开发语言
马优晨20 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
维天说1 天前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane19941 天前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
噢,我明白了1 天前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品1 天前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘1 天前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记1 天前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端