第41天

2023/6/15

# 第41天

# Java 序列化

Java 序列化是一种将对象转换为字节流的过程,以便可以将对象保存到磁盘上,将其传输到网络上,或者将其存储在内存中,以后再进行反序列化,将字节流重新转换为对象。

序列化在 Java 中是通过 java.io.Serializable 接口来实现的,该接口没有任何方法,只是一个标记接口,用于标识类可以被序列化。

当你序列化对象时,你把它包装成一个特殊文件,可以保存、传输或存储。反序列化则是打开这个文件,读取序列化的数据,然后将其还原为对象,以便在程序中使用。

序列化是一种用于保存、传输和还原对象的方法,它使得对象可以在不同的计算机之间移动和共享,这对于分布式系统、数据存储和跨平台通信非常有用。

import java.io.Serializable;

public class MyClass implements Serializable {
    // 类的成员和方法
}

序列化对象: 使用 ObjectOutputStream 类来将对象序列化为字节流,以下是一个简单的实例:

MyClass obj = new MyClass();
try {
    FileOutputStream fileOut = new FileOutputStream("object.ser");
    ObjectOutputStream out = new ObjectOutputStream(fileOut);
    out.writeObject(obj);
    out.close();
    fileOut.close();
} catch (IOException e) {
    e.printStackTrace();
}

反序列化对象: 使用 ObjectInputStream 类来从字节流中反序列化对象,以下是一个简单的实例:

MyClass obj = null;
try {
    FileInputStream fileIn = new FileInputStream("object.ser");
    ObjectInputStream in = new ObjectInputStream(fileIn);
    obj = (MyClass) in.readObject();
    in.close();
    fileIn.close();
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

实例

public class Employee implements java.io.Serializable
{
   public String name;
   public String address;
   public transient int SSN;
   public int number;
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + name
                           + " " + address);
   }
}

Java 序列化是将对象的状态信息转换为可以存储或传输的形式的过程。在 Java 中,序列化通过实现 java.io.Serializable 接口来完成。序列化的主要用途包括对象的持久化存储和网络传输。

# 实现原理

  1. 实现 Serializable 接口:要使一个类支持序列化,该类必须实现 java.io.Serializable 接口。这个接口是一个标记接口,没有方法需要实现。

  2. 对象输出流:使用 ObjectOutputStream 类将对象写入到输出流中,实现对象的序列化。

  3. 对象输入流:使用 ObjectInputStream 类从输入流中读取对象,实现对象的反序列化。

# 主要方法

  1. 序列化对象
  2. 反序列化对象

# 用途

  1. 对象持久化:将对象的状态保存到文件或数据库中,以便在程序下次运行时恢复对象的状态。
  2. 网络传输:将对象序列化为字节流,通过网络发送到另一台计算机,然后在那里反序列化为对象。

# 注意事项

  1. 版本控制:在序列化过程中,Java 会将类的信息(包括类名、成员变量等)写入到序列化流中。如果类的结构发生变化,可能会导致反序列化失败。为了解决这个问题,可以在类中定义一个 serialVersionUID 字段来指定类的版本。
  2. 安全性:序列化可能会暴露对象的内部状态,因此在处理不可信数据时需要谨慎。
  3. 性能:序列化和反序列化操作可能会消耗较多的时间和内存,因此在性能敏感的应用中需要考虑优化。

# 示例代码

import java.io.*;

public class SerializationExample implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;

    public SerializationExample(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {
        // 序列化对象
        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.ser"));
            oos.writeObject(new SerializationExample("Alice", 30));
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 反序列化对象
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.ser"));
            SerializationExample obj = (SerializationExample) ois.readObject();
            ois.close();
            System.out.println(obj.name + ", " + obj.age); // 输出: Alice, 30
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们定义了一个 SerializationExample 类,它实现了 Serializable 接口,并定义了一个 serialVersionUID 字段。在 main 方法中,我们首先创建了一个 SerializationExample 对象,并将其序列化到文件中。然后,我们从文件中反序列化对象,并打印出对象的状态。


学习编程就像搭积木,一块一块慢慢来,下一篇继续加油!