Java - Serialization
Java cung cấp một cơ chế, được gọi là tuần tự hóa đối tượng trong đó một đối tượng có thể được biểu diễn dưới dạng một chuỗi các byte bao gồm dữ liệu của đối tượng cũng như thông tin về kiểu của đối tượng và các kiểu dữ liệu được lưu trữ trong đối tượng.
Sau khi một đối tượng tuần tự hóa đã được ghi vào một tệp, nó có thể được đọc từ tệp và được giải mã hóa, thông tin kiểu và byte đại diện cho đối tượng và dữ liệu của nó có thể được sử dụng để tạo lại đối tượng trong bộ nhớ.
Ấn tượng nhất là toàn bộ quy trình là JVM độc lập, có nghĩa là một đối tượng có thể được tuần tự hóa trên một nền tảng và được giải mã trên một nền tảng hoàn toàn khác.
Các lớp học ObjectInputStream và ObjectOutputStream là các luồng cấp cao chứa các phương thức tuần tự hóa và giải mã hóa một đối tượng.
Lớp ObjectOutputStream chứa nhiều phương thức ghi để ghi các kiểu dữ liệu khác nhau, nhưng một phương thức đặc biệt nổi bật:
public final void writeObject(Object x) throws IOException
Phương thức trên tuần tự hóa một Đối tượng và gửi nó đến luồng đầu ra. Tương tự, lớp ObjectInputStream chứa phương thức sau để giải mã hóa một đối tượng:
public final Object readObject() throws IOException, ClassNotFoundException
Phương thức này truy xuất Đối tượng tiếp theo ra khỏi luồng và giải mã hóa nó. Giá trị trả về là Đối tượng, vì vậy bạn sẽ cần truyền nó sang kiểu dữ liệu thích hợp.
Để chứng minh cách tuần tự hóa hoạt động trong Java, tôi sẽ sử dụng lớp Employee mà chúng ta đã thảo luận sớm trong cuốn sách. Giả sử rằng chúng ta có lớp Employee sau, lớp này thực hiện giao diện Serializable -
Thí dụ
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);
}
}
Lưu ý rằng để một lớp được tuần tự hóa thành công, hai điều kiện phải được đáp ứng:
Lớp phải triển khai giao diện java.io.Serializable.
Tất cả các trường trong lớp phải có thể tuần tự hóa. Nếu một trường không thể tuần tự hóa, nó phải được đánh dấutransient.
Nếu bạn muốn biết liệu Lớp chuẩn Java có thể tuần tự hóa hay không, hãy kiểm tra tài liệu về lớp đó. Kiểm tra rất đơn giản: Nếu lớp thực thi java.io.Serializable, thì nó có thể tuần tự hóa; nếu không, nó không phải.
Sắp xếp thứ tự một đối tượng
Lớp ObjectOutputStream được sử dụng để tuần tự hóa một Đối tượng. Chương trình SerializeDemo sau đây khởi tạo một đối tượng Employee và tuần tự hóa nó thành một tệp.
Khi chương trình được thực thi xong, một tệp có tên là worker.ser được tạo. Chương trình không tạo ra bất kỳ đầu ra nào, nhưng hãy nghiên cứu mã và cố gắng xác định chương trình đang làm gì.
Note - Khi tuần tự hóa một đối tượng vào một tệp, quy ước tiêu chuẩn trong Java là cung cấp cho tệp .ser sự mở rộng.
Thí dụ
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();
}
}
}
Giải mã hóa một đối tượng
Chương trình DeserializeDemo sau đây giải mã hóa đối tượng Employee được tạo trong chương trình SerializeDemo. Nghiên cứu chương trình và cố gắng xác định đầu ra của nó -
Thí dụ
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);
}
}
Điều này sẽ tạo ra kết quả sau:
Đầu ra
Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101
Dưới đây là những điểm quan trọng cần lưu ý:
Khối try / catch cố gắng bắt một ClassNotFoundException, được khai báo bởi phương thức readObject (). Để một JVM có thể giải mã hóa một đối tượng, nó phải có khả năng tìm thấy mã bytecode cho lớp. Nếu JVM không thể tìm thấy một lớp trong quá trình giải mã hóa một đối tượng, nó sẽ ném ra một ClassNotFoundException.
Lưu ý rằng giá trị trả về của readObject () được truyền đến một tham chiếu Nhân viên.
Giá trị của trường SSN là 11122333 khi đối tượng được tuần tự hóa, nhưng vì trường là tạm thời, giá trị này không được gửi đến luồng đầu ra. Trường SSN của đối tượng Nhân viên được deserialized là 0.