Java 简明教程
Java - Serialization
Java 提供了一种机制,称为对象序列化,其中一个对象可以表示为包含该对象的数据以及有关对象类型和存储在 object中的数据类型的信息的字节序列。
Java provides a mechanism, called object serialization where an object can be represented as a sequence of bytes that includes the object’s data as well as information about the object’s type and the types of data stored in the object.
将序列化对象写到文件后,可以从文件读取它并对其反序列化,即类型信息和表示对象及其数据的字节可用于在内存中重新创建该对象。
After a serialized object has been written into a file, it can be read from the file and deserialized that is, the type information and bytes that represent the object and its data can be used to recreate the object in memory.
最令人印象深刻的是,整个过程都是 JVM独立,这意味着一个对象可以在一个平台上序列化,并在一个完全不同的平台上反序列化。
Most impressive is that the entire process is JVM independent, meaning an object can be serialized on one platform and deserialized on an entirely different platform.
Methods for Serializing and Deserializing an Object
类 ObjectInputStream和 ObjectOutputStream是包含用于序列化和反序列化对象的方法的高级流。
Classes ObjectInputStream and ObjectOutputStream are high-level streams that contain the methods for serializing and deserializing an object.
ObjectOutputStream 类包含很多用于写入各种 data types的写入方法,但有一个方法特别突出−
The ObjectOutputStream class contains many write methods for writing various data types, but one method in particular stands out −
Syntax
public final void writeObject(Object x) throws IOException
以上方法对 Object 序列化并将它发送到输出流中。类似地,ObjectInputStream 类包含以下用于反序列化对象的 -
The above method serializes an Object and sends it to the output stream. Similarly, the ObjectInputStream class contains the following method for deserializing an object −
Syntax
public final Object readObject() throws IOException, ClassNotFoundException
此方法从流中检索下一个 Object 并对其进行反序列化。返回值为 Object,因此你需要将其强制转换为其适当的数据类型。
This method retrieves the next Object out of the stream and deserializes it. The return value is Object, so you will need to cast it to its appropriate data type.
How Serialization Works in Java?
为了演示序列化如何在 Java 中工作,我将使用我们在本书开头讨论过的 Employee 类。假设我们有以下一个实现了 Serializable 接口的 Employee 类:
To demonstrate how serialization works in Java, I am going to use the Employee class that we discussed early on in the book. Suppose that we have the following Employee class, which implements the Serializable interface −
Example to Demonstrate Working of Serialization in Java
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);
}
}
请注意,若要成功序列化一个类,必须满足两个条件:
Notice that for a class to be serialized successfully, two conditions must be met −
-
The class must implement the java.io.Serializable interface.
-
All of the fields in the class must be serializable. If a field is not serializable, it must be marked transient.
如果你好奇一个 Java 标准类是否可序列化,请查看该类的文档。测试很简单:如果该类实现了 java.io.Serializable,那么它是可序列化的;否则,它不可序列化。
If you are curious to know if a Java Standard Class is serializable or not, check the documentation for the class. The test is simple: If the class implements java.io.Serializable, then it is serializable; otherwise, it’s not.
Serializing an Object
ObjectOutputStream 类用于序列化一个对象。以下 SerializeDemo 程序实例化一个 Employee 对象,并将其序列化到一个文件中。
The ObjectOutputStream class is used to serialize an Object. The following SerializeDemo program instantiates an Employee object and serializes it to a file.
当程序执行完毕时,会创建一个名为 employee.ser 的文件。该程序不会生成任何输出,但研究该代码,并尝试确定该程序正在做什么。
When the program is done executing, a file named employee.ser is created. The program does not generate any output, but study the code and try to determine what the program is doing.
Note - 当将一个对象序列化到一个文件中时,Java 中的标准惯例是给该文件一个 .ser 扩展名。
Note − When serializing an object to a file, the standard convention in Java is to give the file a .ser extension.
Example for Serializing an Object
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
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("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();
}
}
}
class Employee implements java.io.Serializable {
private static final long serialVersionUID = 1L;
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);
}
}
Serialized data is saved in employee.ser
Deserializing an Object
以下 DeserializeDemo 程序反序列化在前面程序中创建的 Employee 对象。研究该程序并尝试确定其输出:
The following DeserializeDemo program deserializes the Employee object created in the earlier program. Study the program and try to determine its output −
Example for Deserializing an Object
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
FileInputStream fileIn = new FileInputStream("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);
}
}
class Employee implements java.io.Serializable {
private static final long serialVersionUID = 1L;
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);
}
}
Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101
Importing Points About Serialization in Java
以下是要注意的几个重点:
Here are following important points to be noted −
-
The try/catch block tries to catch a ClassNotFoundException, which is declared by the readObject() method. For a JVM to be able to deserialize an object, it must be able to find the bytecode for the class. If the JVM can’t find a class during the deserialization of an object, it throws a ClassNotFoundException.
-
Notice that the return value of readObject() is cast to an Employee reference.
-
The value of the SSN field was 11122333 when the object was serialized, but because the field is transient, this value was not sent to the output stream. The SSN field of the deserialized Employee object is 0.