Java基础——序列化与反序列化

59 阅读3分钟

什么是序列化?

由于在实际的网络传输的数据必须是二进制数据,但是调用方法请求的出入参数都是对象。对象时不能够直接在网络上进行传输的,所以需要提前将其转换为可传输的二进制,并且要求转换算法是可逆的。

  • 序列化:序列化就是将对象转换为二进制数据。
  • 反序列化:反序列化就是将二进制数据转换为对象。

使用场景:

序列化和反序列化在很多场景中都非常有用:

数据存储:将程序中的数据保存到文件或者是数据库中,方便以后重新加载和使用。

网络通信:在网络上传输数据时候,需要将数据序列化为字节流,以便在接收端进行反序列化。

常见的序列化格式包括 JSON(JavaScript Object Notation)、XML(eXtensible Markup Language)、Protocol Buffers、MessagePack等。每种格式有其优势和适用场景,选择合适的序列化格式取决于具体的应用需求。

Java序列化小例子

创建一个对象,将对象进行序列化,放入.Class文件中,之后进行反序列化,将预存储的对象从文件中读取出来

package com.nylonmin.serialize;
​
​
import java.io.*;
​
public class Seridemo {
    public static final File SAVEFILE = new File("F:"+File.separator+"demo.Class");
​
    //序列化
    //Java的序列化就是将对象写入到文件或者是将其变为二进制
    public static void saveObj(Object object) throws IOException {
        //创建ObjectOutputStream对象
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(SAVEFILE));
        //将通过形参传入进来的对象输出到文件中
        objectOutputStream.writeObject(object);
        return;
    }
​
    //反序列化
    //Java的反序列化就是将文件中原来存储的对象数据读到对象中
    public static Object readObj() throws Exception {
        //创建ObjectInputStream对象
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(SAVEFILE));
        //读取对象
        Object obj = objectInputStream.readObject();
        return obj;
​
​
    }
    public static void main(String[] args) throws Exception {
        Person person = new Person("张三",1,20,new House("A省B市",100000));
        Seridemo.saveObj(person);
        Seridemo.readObj();
​
    }
​
​
    public static class Person  implements Serializable {
        private String name;
        private int id;
        private int age;
        private House house;
        public Person(){}
​
        public Person(String name, int id, int age, House house) {
            this.name = name;
            this.id = id;
            this.age = age;
            this.house = house;
        }
​
        public String getName() {
            return name;
        }
​
        public void setName(String name) {
            this.name = name;
        }
​
        public int getId() {
            return id;
        }
​
        public void setId(int id) {
            this.id = id;
        }
​
        public int getAge() {
            return age;
        }
​
        public void setAge(int age) {
            this.age = age;
        }
​
        public House getHouse() {
            return house;
        }
​
        public void setHouse(House house) {
            this.house = house;
        }
    }
    private static class House implements Serializable{
        private String location;
        private int price;
​
        public House(){}
​
        public House(String location, int price) {
            this.location = location;
            this.price = price;
        }
​
        public String getLocation() {
            return location;
        }
​
        public void setLocation(String location) {
            this.location = location;
        }
​
        public int getPrice() {
            return price;
        }
​
        public void setPrice(int price) {
            this.price = price;
        }
    }
}
​

我们可以通过打断点调试的方式来看具体的细节:

序列化:

Snipaste_2024-10-30_16-21-51.png

反序列化:

Snipaste_2024-10-30_16-21-21.png

注:

这里面有几个需要注意的点

public static final File SAVEFILE = new File("F:"+File.separator+"demo.Class");

  • File.separator

    • File.separator:是一个静态字段,它包含了操作系统特定的文件路径分隔符。在 Windows 系统中,File.separator 的值是反斜杠 ``,而在 Unix/Linux 系统中,它的值是正斜杠 /。使用 File.separator 可以确保你的代码在不同的操作系统上都能正确处理文件路径。
  • .Class文件

    • .Class 文件是 Java 编译后生成的字节码文件
    • .class 文件的具体内容是二进制格式的