Java 序列化

Java 序列化

Java提供了一种机制,称为对象序列化,其中一个对象可以被表示为包含对象数据以及关于对象类型和存储在对象中的数据类型的信息的字节序列。

将序列化对象写入文件后,可以从文件中读取和反序列化,即可以使用类型信息和表示对象及其数据的字节来在内存中重新创建对象。

最令人印象深刻的是整个过程独立于JVM,这意味着一个对象可以在一个平台上进行序列化并在完全不同的平台上进行反序列化。

ObjectInputStreamObjectOutputStream 类是高级流,包含用于序列化和反序列化对象的方法。

ObjectOutputStream类中包含许多写入各种数据类型的方法,但有一个方法特别突出-

public final void writeObject(Object x) throws IOException

上面的方法将一个对象序列化并发送到输出流。类似地,ObjectInputStream类包含以下方法来对对象进行反序列化 –

public final Object readObject() throws IOException, ClassNotFoundException

这个方法从流中获取下一个对象并进行反序列化。返回值是Object,所以你需要将其转换为适当的数据类型。

为了演示Java中的序列化是如何工作的,我将使用书中早些时候讨论过的Employee类。假设我们有以下实现了Serializable接口的Employee类:

示例

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.io.Serializable接口。

  • 该类的所有字段必须可序列化。如果一个字段不可序列化,它必须被标记为 transient。

如果你想知道一个Java标准类是否可序列化,请查阅该类的文档。测试很简单:如果该类实现了java.io.Serializable接口,则它是可序列化的;否则,它是不可序列化的。

对象的序列化

ObjectOutputStream类用于序列化一个对象。下面的SerializeDemo程序实例化了一个Employee对象,并将其序列化到一个文件中。

当程序执行完成时,将创建一个名为employee.ser的文件。程序不会生成任何输出,但请研究代码并尝试确定程序正在做什么。

注意 - 当将一个对象序列化到文件时,Java的标准约定是给文件一个 .ser 扩展名。

示例

import java.io.*;
public class SerializeDemo {

   public static void main(String [] args) {
      Employee e = new Employee();
      e.name = "Reyan Ali";
      e.address = "Phokka Kuan, Ambehta Peer";
      e.SSN = 11122333;
      e.number = 101;

      try {
         FileOutputStream fileOut =
         new FileOutputStream("/tmp/employee.ser");
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in /tmp/employee.ser");
      } catch (IOException i) {
         i.printStackTrace();
      }
   }
}

反序列化对象

以下是DeserializeDemo程序,用于反序列化在SerializeDemo程序中创建的Employee对象。研究该程序并尝试确定其输出结果 –

示例

import java.io.*;
public class DeserializeDemo {

   public static void main(String [] args) {
      Employee e = null;
      try {
         FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
         ObjectInputStream in = new ObjectInputStream(fileIn);
         e = (Employee) in.readObject();
         in.close();
         fileIn.close();
      } catch (IOException i) {
         i.printStackTrace();
         return;
      } catch (ClassNotFoundException c) {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }

      System.out.println("Deserialized Employee...");
      System.out.println("Name: " + e.name);
      System.out.println("Address: " + e.address);
      System.out.println("SSN: " + e.SSN);
      System.out.println("Number: " + e.number);
   }
}

这将产生以下结果 −

Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101

以下是需要注意的重要点:

  • try/catch块尝试捕获ClassNotFoundException异常,该异常由readObject()方法声明。对于JVM来说,要能够反序列化一个对象,它必须能够找到该类的字节码。如果JVM在对象反序列化过程中找不到一个类,它会抛出一个ClassNotFoundException异常。

  • 请注意,readObject()的返回值被强制转换为Employee引用。

  • SSN字段的值在对象序列化时为11122333,但由于该字段是瞬态的,这个值没有被发送到输出流。反序列化后的Employee对象的SSN字段为0。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程