Java提供了一种称为对象序列化的机制,其中对象可以表示为一个字节序列,其中包括对象的数据以及有关对象类型和存储在对象中的数据类型的信息。
将序列化对象写入文件后,可以从文件中读取该对象并进行反序列化,即表示对象及其数据的类型信息和字节可用于在内存中重新创建对象 。
类ObjectInputStream和ObjectOutputStream用于序列化和反序列化对象的方法。
ObjectOutputStream类包含许多用于写入各种数据类型的写入方法,但其中一种方法尤其引人注目-
public final void writeObject(Object x) throws IOException
上述方法序列化对象并将其发送到输出流。同样,ObjectInputStream类包含以下用于反序列化对象-的方法
public final Object readObject() throws IOException, ClassNotFoundException
此方法检索流中的下一个对象并将其反序列化。返回值是对象,因此需要将其强制转换为相应的数据类型。
为了演示序列化如何在Java中工作,无涯教程将使用在本书前面讨论的Employee类。假设有以下Employee类,该类实现Serializable接口-
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 关键字。
序列化对象
ObjectOutputStream类用于序列化对象。 下面的SerializeDemo程序化一个Employee 对象,并将其序列化为文件。
当程序完成执行时,将创建一个名为employee e.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;
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="typ">FileOutputStream</span><span class="pln"> fileOut </span><span class="pun">=</span><span class="pln">
</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FileOutputStream</span><span class="pun">(</span><span class="str">"/tmp/employee.ser"</span><span class="pun">);</span><span class="pln">
</span><span class="typ">ObjectOutputStream</span><span class="pln"> </span><span class="kwd">out</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ObjectOutputStream</span><span class="pun">(</span><span class="pln">fileOut</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">writeObject</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span><span class="pln">
fileOut</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span><span class="pln">
</span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">printf</span><span class="pun">(</span><span class="str">"Serialized data is saved in /tmp/employee.ser"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">IOException</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
i</span><span class="pun">.</span><span class="pln">printStackTrace</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
}
}
反序列化对象
以下desializeDemo程序对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;
}
</span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Deserialized Employee..."</span><span class="pun">);</span><span class="pln">
</span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Name: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
</span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Address: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">address</span><span class="pun">);</span><span class="pln">
</span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"SSN: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">SSN</span><span class="pun">);</span><span class="pln">
</span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Number: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">number</span><span class="pun">);</span><span class="pln">
}
}
这将产生以下输出-
Deserialized Employee... Name: Reyan Ali Address:Phokka Kuan, Ambehta Peer SSN: 0 Number:101
以下是-需要注意的要点
try/catch块尝试捕获由readObject()方法声明的ClassNotFoundException。如果反序列化过程中找不到类,它会抛出ClassNotFoundException。
请注意,readObject()的返回值被强制转换为Employee对象。
当对象被序列化时,ssn字段的值是11122333,但由于该字段是瞬态(transient)的,所以这个值没有被发送到输出流。反序列化Employee对象SSN字段为0。