+26

Java - Serialization

Serialization là gì?

Serialization đơn giản chỉ là chuyển từ một object tồn tại thành một mảng byte. Mảng byte này đại diện cho class của object, phiên bản của object, và trạng thái của object. Mảng byte này có thể được sử dụng giữa các máy ảo JVM đang chạy cùng code truyền / đọc các object. Ngược lại Deserialization là quá trình xây dựng lại các byte vào một đối tượng. Java Serialization API cung cấp một cơ chế chuẩn cho các nhà phát triển để xử lý đối tượng. Trong bài viết này, bạn sẽ thấy làm thế nào để serialize một đối tượng, và tại sao serialization đôi khi là cần thiết.

Tại sao Serialization lại cần thiết?

Trong thế giới ngày nay, một ứng dụng doanh nghiệp điển hình sẽ có nhiều thành phần và sẽ được phân phối trên các hệ thống và mạng khác nhau. Trong Java, mọi thứ được biểu diễn dưới dạng các đối tượng; Nếu hai thành phần Java muốn giao tiếp với nhau, cần phải có một cơ chế để trao đổi dữ liệu. Một cách để đạt được điều này là xác định giao thức của riêng bạn và chuyển một đối tượng. Điều này có nghĩa là đầu nhận phải biết giao thức được sử dụng bởi người gửi để tạo lại đối tượng, điều này làm cho việc nói chuyện với các thành phần của bên thứ ba rất khó khăn. Do đó, cần phải có một giao thức chung chung và hiệu quả để chuyển đối tượng giữa các thành phần. Serialization được định nghĩa cho mục đích này, và các thành phần Java sử dụng giao thức này để chuyển các đối tượng.

Ví dụ về Serialization và Deserialization

Để mà serialize một object, bạn cần phải đảm bảo rằng class của object đó implements java.io.Serializable interface. Serializable interface chỉ là một marker interface, bản thân nó chẳng định nghĩa 1 phương thức nào cả 😄, nó chỉ có nhiệm vụ chỉ ra đây là object có thể serialized được.

Hai lớp ObjectInputStream và ObjectOutputStream chứa các phương thức dùng để serializing và deserializing một object. ObjectOutputStream : public final void writeObject(Object x) throws IOException => đây là phương thức để serializes một Object và gửi nó đến một output stream ObjectInputStream : public final Object readObject() throws IOException, ClassNotFoundException => đây là phương thức để lấy ra object từ stream và deserializes nó. Giá trị trả về là một object, vì vậy bạn cần phải ép kiểu cho nó.

OK, bây giờ chúng ta sẽ đi vào ví dụ cụ thể ^^!

Chúng ta có 1 lớp Employee như sau

package vuta.serialization.example;

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 ý:

  • Phải implement the java.io.Serializable interface, nếu không java.io.NotSerializableException sẽ xảy ra
  • Tất cả các thuộc tính trong class phải serializable. Nếu thuộc tính nào không serializable, nó phải được dùng từ khóa transient.

Serializing một Object

Ví dụ dưới đây khởi tạo 1 object Employee, sau đó serializes nó và lưu vào 1 file.

package vuta.serialization.example;

import java.io.*;

public class SerializeDemo {

	public static void main(String[] args) {
		Employee e = new Employee();
		e.name = "Tran Anh Vu";
		e.address = "138 Le Duan - P.Nguyen Du - Q.Hai Ba Trung - Ha Noi";
		e.SSN = 11122333;
		e.number = 101;

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

Deserializing một Object

package vuta.serialization.example;

import java.io.*;

public class DeserializeDemo {

	public static void main(String[] args) {
		Employee e = null;
		try {
			FileInputStream fileIn = new FileInputStream("C:\\employee.data");
			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);
	}
}

Lưu ý:

  • Thuộc tính SSN có giá trị 11122333 khi mà object được serialized, nhưng bởi vì nó được đặt từ khóa transient nên giá trị của nó không được gửi đến output stream. Vì vậy sau khi deserialize nó mới có giá trị là 0.

Java's serialization algorithm

Bây giờ chúng ta đã có kiến thức về làm thế nào để serialize và deserialize một object rồi. Vậy cơ chế làm việc ẩn phía dưới là gì? OK, đây là câu trả lời:

  1. Đầu tiên ghi ra metadata của class mà liên quan đến instance được serialize
  2. Tiếp theo đệ quy ghi ra mô tả của lớp cha cho đến khi tìm thấy java.lang.object.
  3. Một khi kết thúc ghi ra metadata của tất cả các class, đệ quy ghi với dữ liệu thực tế liên quan đến các class. Nhưng lần này, bắt đầu từ lớp superclass trên cùng(Object).

Một vài điểm cần lưu ý

  1. Nếu superclass là Serializable thì các lớp con của nó sẽ tự động được Serializable.
  2. Khi bạn serialize bất kỳ object nào mà nó có chứa tham chiếu đến object khác thì Java serialization sẽ serialize luôn cả object đó (nếu object được tham chiếu không implement the java.io.Serializable interface thì java.io.NotSerializableException sẽ xảy ra
  3. Bạn không thể serialize các biến static

Hy vọng rằng bài viết này hữu ích đối với các bạn!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí