Java 序列化和反序列化

原文:https://www.studytonight.com/java/serialization-and-deserialization.php

序列化是将一个对象转换成一个字节序列的过程,该字节序列可以保存到磁盘或数据库中,也可以通过流发送。从字节序列创建对象的相反过程称为反序列化

一个类必须实现java.io包中存在的可序列化接口,才能成功序列化其对象。 Serializable 是一个标记接口,它为实现它的类增加了可序列化的行为。

Java 提供封装在java.io包下的 Serializable API,用于序列化和反序列化对象,包括:

  • java.io.serializable
  • java.io.Externalizable
  • ObjectInputStream
  • ObjectOutputStream

Java 标记接口

标记接口是 Java 中的一个特殊接口,没有任何字段和方法。标记接口用于通知编译器实现它的类有一些特殊的行为或意义。标记界面一些例子是,

  • java.io.serializable
  • java.lang.Cloneable
  • java.rmi.Remote
  • java.util.RandomAccess

所有这些接口都没有任何方法和字段。它们只给实现它们的类添加特殊行为。然而,标记接口从 Java 5 开始就被弃用了,它们被注释所取代。注释被用来代替标记接口,其作用与标记接口之前的作用完全相同。

为了实现序列化和反序列化,Java 提供了两个类 ObjectOutputStream 和 ObjectInputStream。

对象输出流类

它用于将对象状态写入文件。实现 java.io.Serializable 接口的对象可以写入 strams。它提供了各种方法来执行序列化。

ObjectInputStream 类

ObjectInputStream 反序列化使用 ObjectOutputStream 编写的对象和原始数据。

writeObject()readObject()方法

ObjectOutputStream类的writeObject()方法序列化一个对象并将其发送到输出流。

public *final* void **writeObject**(*object x*) throws **IOException**

ObjectInputStream类的readObject()方法引用流外的对象并反序列化它。

public final *Object* **readObject()** throws **IOException,ClassNotFoundException**

在序列化时,如果您不想让任何字段成为对象状态的一部分,那么根据您的需要声明它为静态或瞬态,并且在 java 序列化过程中不会包含它。

serialization and deserialization of objects

示例:用 Java 序列化对象

在这个例子中,我们有一个实现 Serializable 接口的类来使它的对象序列化。

import java.io.*;
class Studentinfo implements Serializable
{
    String name;
    int rid;
    static String contact;
    Studentinfo(String n, int r, String c)
    {
    this.name = n;
    this.rid = r;
    this.contact = c;
    }
}

class Demo
{
    public static void main(String[] args)
    {
        try
        {
            Studentinfo si = new Studentinfo("Abhi", 104, "110044");
            FileOutputStream fos = new FileOutputStream("student.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(si);
            oos.flush();
            oos.close();
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }
}

Studentinfo 类的对象使用writeObject()方法序列化并写入student.txt文件。

示例:Java 中对象的反序列化

为了反序列化对象,我们使用 ObjectInputStream 类,该类将从指定的文件中读取对象。见下面的例子。

import java.io.*;

class Studentinfo implements Serializable
{
    String name;
    int rid;
    static String contact;
    Studentinfo(String n, int r, String c)
    {
    this.name = n;
    this.rid = r;
    this.contact = c;
    }
}

class Demo
{
    public static void main(String[] args)
    {
        Studentinfo si=null ;
        try
        {
            FileInputStream fis = new FileInputStream("/filepath/student.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            si = (Studentinfo)ois.readObject();
        }
        catch (Exception e)
        {
            e.printStackTrace(); }
            System.out.println(si.name);
            System.out. println(si.rid);
            System.out.println(si.contact);
        }
}

Abhi 104 是空的

联系人字段为空,因为它被标记为静态,并且正如我们前面讨论的,静态字段不会被序列化。

注意:静态成员从不序列化,因为它们连接到类而不是类的对象。

transient关键字

序列化对象时,如果我们不想序列化对象的某个数据成员,我们可以称之为瞬态。transient 关键字将阻止数据成员被序列化。

class studentinfo implements Serializable 
{
    String name;
    transient int rid;
    static String contact;
}
  • 创建数据成员transient将阻止其序列化。
  • 在本例中rid将不会被序列化,因为它是瞬态,而contact也将保持未序列化,因为它是静态