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

相关推荐
吃炒鸡蛋4 分钟前
反射更新字段
java·服务器·前端
Pacify_The_North19 分钟前
【C++11(二)】可变参数模板和 lambda表达式
java·开发语言·c++
是梦终空25 分钟前
计算机毕业设计248—基于Java+Springboot+vue的博物馆预约系统(源代码+数据库+开发文档)
java·spring boot·vue·毕业设计·jwt·博物馆预约系统·博物馆网站
Tao____30 分钟前
支持mqtt、tcp、udp、websocket、http协议的物联网平台
java·物联网·mqtt·websocket·tcp/ip·udp
poggioxay37 分钟前
JAVA零基础入门知识3(持续更新中)
java·开发语言·python
清晓粼溪1 小时前
SpringMVC-01:基础知识
java·spring
互亿无线明明1 小时前
如何为全球业务构建可扩展的“群发国际短信接口”?
java·c++·python·golang·eclipse·php·erlang
写完代码就回家结婚1 小时前
Java函数式编程:用Stream API重构你的代码逻辑
java
琢瑜2 小时前
问题1:Oracle Java路径干扰。问题2:环境变量加载顺序问题
java·maven
Yang-Never2 小时前
Open GL ES->以指定点为中心缩放图片纹理的完整图解
android·java·开发语言·kotlin·android studio