掘金 后端 ( ) • 2024-04-30 19:18

序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在Java中,这通常意味着将对象转换为字节流,以便可以将其保存到磁盘上或通过网络传输到另一个网络节点。相反,反序列化(Deserialization)是将已序列化的数据恢复为对象的过程。

序列化的基本概念

为了能够序列化,一个类必须实现java.io.Serializable接口。这是一个标记接口(没有方法的接口),用于告知JVM该类的对象可以被序列化。

序列化的过程

序列化过程涉及使用java.io.ObjectOutputStream类。它包装了一个底层的OutputStream,比如FileOutputStream,用于将序列化的对象数据写入文件或其他类型的流。

代码演示:序列化

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

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

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public static void main(String[] args) {
        Student student = new Student("John Doe", 22);
        try (FileOutputStream fileOut = new FileOutputStream("student.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            out.writeObject(student);
            System.out.println("Object has been serialized");
        } catch (IOException i) {
            i.printStackTrace();
        }
    }
}

反序列化的过程

反序列化过程使用java.io.ObjectInputStream类。它包装了一个底层的InputStream,如FileInputStream,用于从文件或其他类型的流中读取并恢复对象数据。

代码演示:反序列化

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserializeStudent {
    public static void main(String[] args) {
        Student student = null;
        try (FileInputStream fileIn = new FileInputStream("student.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            student = (Student) in.readObject();
            System.out.println("Object has been deserialized");
            System.out.println("Name: " + student.name + ", Age: " + student.age);
        } catch (IOException i) {
            i.printStackTrace();
            return;
        } catch (ClassNotFoundException c) {
            System.out.println("Student class not found");
            c.printStackTrace();
            return;
        }
    }
}

序列化中的重要考虑

  • serialVersionUID的角色serialVersionUID是序列化对象的版本标识符。它用于验证序列化对象的发送方和接收方是否加载了与序列化兼容的类。
  • transient关键字:如果不希望对象的某个属性被序列化,可以使用transient关键字声明这个属性。被transient修饰的属性在序列化过程中会被忽略。
  • 安全性:序列化可能会导致安全问题,因为反序列化时,攻击者可能会修改序列化数据以破坏应用程序的安全性。因此,对于敏感或安全性要求高的数据,需要谨慎使用序列化。

总结

序列化和反序列化是Java编程中处理对象持久化和数据传输的重要技术。通过实现Serializable接口并使用ObjectOutputStreamObjectInputStream,Java类的对象可以轻松地写入到文件或在网络中传输,并可以从中恢复。然而,开发者需要注意序列化的安全性和serialVersionUID等细节,以确保应用程序的正确性和安全性。