likes
comments
collection
share

Java序列化和反序列化:玩转对象的“变形金刚”能力!

作者站长头像
站长
· 阅读数 27

《Java零基础教学》是一套深入浅出的 Java 编程入门教程。全套教程从Java基础语法开始,适合初学者快速入门,同时也从实例的角度进行了深入浅出的讲解,让初学者能够更好地理解Java编程思想和应用。

本教程内容包括数据类型与运算、流程控制、数组、函数、面向对象基础、字符串、集合、异常处理、IO 流及多线程等 Java 编程基础知识,并提供丰富的实例和练习,帮助读者巩固所学知识。本教程不仅适合初学者学习,也适合已经掌握一定 Java 基础的读者进行查漏补缺。

前言

在 Java 开发中,我们经常需要将一个对象转换成字节数组或字符串进行传输和存储。Java 序列化 (Serialization) 和反序列化 (Deserialization) 是实现这一目的的重要手段。本文将介绍 Java 序列化和反序列化的基本概念和实现方法,并通过示例程序演示它们的使用。

摘要

本文首先介绍了 Java 序列化和反序列化的基本概念,包括其作用、原理和注意事项。接着,我们讲解了如何在 Java 中实现序列化和反序列化操作,包括使用 Serializable 接口和 Externalizable 接口实现对象的序列化和反序列化。最后,我们通过示例程序演示了 Java 序列化和反序列化的使用方法,包括对象的序列化和反序列化、文件的序列化和反序列化等。

内容

Java 序列化和反序列化是 Java 编程中常用的一种数据转换方式,它们的主要作用是将 Java 对象转换成字节数组或字符串进行传输和存储。Java 序列化和反序列化的具体实现基于 Java 中的 Serializable 接口和 Externalizable 接口。

Serializable 接口

Serializable 接口是 Java 中的一个标记接口,用于标识一个类的实例可以被序列化。一个类只有实现了 Serializable 接口,才能被序列化为字节数组或字符串。

public interface Serializable {

}

在实现 Serializable 接口的类中,可以定义一个名为 serialVersionUID 的静态常量,用于标识该类的版本号。当反序列化时,Java 虚拟机会根据类的版本号来检查反序列化对象与当前类是否兼容。

public class User implements Serializable {
    private String name;
    private int age;
    private static final long serialVersionUID = 1L; // 版本号
    // ...
}

Externalizable 接口

Externalizable 接口继承了 Serializable 接口,它定义了两个方法:writeExternal() 和 readExternal(),用于手动控制对象的序列化和反序列化过程。实现 Externalizable 接口需要重写这两个方法。

public interface Externalizable extends java.io.Serializable {
    void writeExternal(ObjectOutput out) throws IOException;
    void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}

序列化对象

序列化一个 Java 对象的过程需要进行以下操作:

  1. 创建 ObjectOutputStream 对象;
  2. 调用 ObjectOutputStream 的 writeObject() 方法将对象序列化成字节数组或字符串;
  3. 关闭 ObjectOutputStream 对象。
public class SerializableTest {
    public static void main(String[] args) throws IOException {
        User user = new User("Tom", 20);
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.dat"));
        out.writeObject(user);
        out.close();
    }
}

在上述代码中,我们创建了一个 User 对象并将其序列化成一个文件 user.dat。可以通过以下代码反序列化该文件:

public class DeserializableTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.dat"));
        User user = (User) in.readObject();
        in.close();
    }
}

序列化文件

Java 序列化还可以用于文件的序列化和反序列化。例如,我们可以将一个 Java 对象序列化成文件,然后在需要的时候将其反序列化出来,而不是每次重新构造对象。代码如下:

public class SerializableFileTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        User user = new User("Tom", 20);
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.dat"));
        out.writeObject(user);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.dat"));
        User user2 = (User) in.readObject();
        in.close();
    }
}

注意事项

在 Java 序列化和反序列化过程中,需要注意以下事项:

  1. 被序列化的对象必须实现 Serializable 接口或 Externalizable 接口;
  2. 被序列化的对象的所有实例变量必须是可序列化的。如果一个对象包含了一个不可序列化的实例变量,则序列化操作会失败;
  3. 被序列化的对象中的静态变量不会被序列化;
  4. 被序列化的对象中的 transient 关键字修饰的变量不会被序列化。

代码方法介绍

  • ObjectOutputStream

    • 构造方法

      public ObjectOutputStream(OutputStream out) throws IOException
      
    • 方法

      public final void writeObject(Object obj) throws IOException
      
  • ObjectInputStream

    • 构造方法

      public ObjectInputStream(InputStream in) throws IOException
      
    • 方法

      public final Object readObject() throws IOException, ClassNotFoundException
      

测试用例

我们可以通过以下测试用例来验证 Java 序列化和反序列化的正确性:

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        User user = new User("Tom", 20);

        // 将 User 对象序列化成字节数组
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(user);
        byte[] bytes = bos.toByteArray();

        // 将字节数组反序列化成 User 对象
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        ObjectInputStream in = new ObjectInputStream(bis);
        User user2 = (User) in.readObject();

        // 验证两个 User 对象是否相同
        System.out.println(user.equals(user2)); // true
    }

测试用例执行如下:

Java序列化和反序列化:玩转对象的“变形金刚”能力!

全文小结

本文介绍了 Java 序列化和反序列化的基本概念和实现方法,包括使用 Serializable 接口和 Externalizable 接口实现对象的序列化和反序列化。我们还通过示例程序演示了 Java 序列化和反序列化的使用方法,包括对象的序列化和反序列化、文件的序列化和反序列化等。在使用 Java 序列化和反序列化时,我们需要注意被序列化的对象的实现方式和实例变量的可序列化性,以确保程序正常运行。

最后

大家如果觉得看了本文有帮助的话,麻烦给个三连(点赞、分享、转发)支持一下哈。