0
0
Lập trình
Thaycacac
Thaycacac thaycacac

Hiểu về Tuần tự hóa (Serialization) trong Java: Quy trình, Lưu ý, và Ví dụ

Đăng vào 5 ngày trước

• 5 phút đọc

1. Giới thiệu về Tuần tự hóa (Serialization)

Tuần tự hóa (Serialization) là quá trình chuyển đổi trạng thái của một đối tượng Java thành một dòng byte, với mục đích lưu trữ hoặc truyền tải thông qua mạng. Phương pháp ngược lại, giải tuần tự hóa (deserialization), cho phép chúng ta chuyển đổi dòng byte trở lại thành đối tượng Java.

2. Serialized và Deserialized

Quá trình tuần tự hóa không phụ thuộc vào phiên bản, cho phép bạn tuần tự hóa đối tượng trên một nền tảng và giải tuần tự hóa trên một nền tảng khác. Để một lớp có thể được tuần tự hóa, nó cần thực thi giao diện đánh dấu Serializable.

Các lớp ObjectInputStreamObjectOutputStream thuộc về các luồng dữ liệu trong java.io và cho phép ghi và đọc đối tượng. Điều quan trọng nhất là hai phương thức sau:

java Copy
public final void writeObject(Object o) throws IOException;

Phương thức này giúp ghi một đối tượng có thể tuần tự hóa thành dòng byte. Tương tự, phương thức sau trong ObjectInputStream:

java Copy
public final Object readObject() throws IOException, ClassNotFoundException;

Phương thức này nhận đầu vào là một luồng byte và trả về một đối tượng Java, có thể được ép kiểu về kiểu dữ liệu gốc.

Ví dụ Về Tuần tự hóa với Lớp Person

Chúng ta sẽ xem xét quá trình tuần tự hóa một lớp đơn giản là Person. Các trường tĩnh (static fields) của lớp sẽ không được tuần tự hóa, vì chúng thuộc về lớp thay vì đối tượng. Từ khóa transient có thể được sử dụng để loại bỏ các trường trong quá trình tuần tự hóa:

java Copy
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    static String country = "ITALY";
    private int age;
    private String name;
    transient int height;

    // getters và setters
}

Dưới đây là ví dụ về việc lưu đối tượng Person vào file và đọc lại:

java Copy
@Test 
public void whenSerializingAndDeserializing_ThenObjectIsTheSame() throws IOException, ClassNotFoundException { 
    Person person = new Person();
    person.setAge(20);
    person.setName("Joe");
    
    FileOutputStream fileOutputStream = new FileOutputStream("yourfile.txt");
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
    objectOutputStream.writeObject(person);
    objectOutputStream.flush();
    objectOutputStream.close();
    
    FileInputStream fileInputStream = new FileInputStream("yourfile.txt");
    ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
    Person p2 = (Person) objectInputStream.readObject();
    objectInputStream.close(); 
    
    assertTrue(p2.getAge() == person.getAge());
    assertTrue(p2.getName().equals(person.getName()));
}

Chúng ta đã sử dụng ObjectOutputStream để lưu trạng thái của đối tượng vào một file, sau đó sử dụng ObjectInputStream để đọc lại. Đảm bảo trạng thái của đối tượng được khôi phục đúng với đối tượng ban đầu.

3. Những Lưu Ý Quan Trọng Về Tuần tự hóa trong Java

3.1 Kế thừa và Thành phần

Khi một lớp thực thi giao diện Serializable, tất cả các lớp con cũng sẽ tự động có khả năng tuần tự hóa. Nếu một đối tượng tham chiếu đến một đối tượng khác, mọi đối tượng này cũng cần thực thi Serializable, ngược lại sẽ gây ra lỗi NotSerializableException.

java Copy
public class Person implements Serializable {
    private int age;
    private String name;
    private Address country; // phải có khả năng tuần tự hóa
}

3.2 Serial Version UID

JVM gán một số phiên bản cho mỗi lớp tuần tự hóa. Số này được sử dụng để xác minh tính tương thích giữa các đối tượng đã lưu và tải. Nếu một lớp không khai báo serialVersionUID, JVM sẽ tự động tạo trong thời gian chạy.

3.3 Tuần tự hóa Tùy Chọn

Java cho phép bạn ghi đè hành vi tuần tự hóa mặc định, điều này hữu ích cho các thuộc tính không thể tuần tự hóa. Để thực hiện điều này, bạn chỉ cần định nghĩa hai phương thức sau trong lớp của bạn:

java Copy
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

Khi đó, bạn có thể kiểm soát cách thức tuần tự hóa các thuộc tính phức tạp hơn.

Ví dụ về Tuần tự hóa Tùy Chọn:

java Copy
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    private transient Address address;
    private Person person;

    // setters và getters

    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();
        oos.writeObject(address.getHouseNumber());
    }

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        ois.defaultReadObject();
        Integer houseNumber = (Integer) ois.readObject();
        Address a = new Address();
        a.setHouseNumber(houseNumber);
        this.setAddress(a);
    }
}

public class Address {
    private int houseNumber;

    // setters và getters
}

Giả sử ta muốn kiểm tra quá trình tuần tự hóa tùy chọn:

java Copy
@Test
public void whenCustomSerializingAndDeserializing_ThenObjectIsTheSame() throws IOException, ClassNotFoundException {
    Person p = new Person();
    p.setAge(20);
    p.setName("Joe");

    Address a = new Address();
    a.setHouseNumber(1);

    Employee e = new Employee();
    e.setPerson(p);
    e.setAddress(a);

    // quá trình tuần tự hóa và giải tuần tự hóa
}

Lưu ý rằng cá thuộc tính không thể tuần tự hóa cần phải đánh dấu là transient.

Kết Luận

Tìm hiểu về tuần tự hóa trong Java không chỉ giúp bạn chuyển đổi đối tượng dễ dàng mà còn mở rộng khả năng lưu trữ và truyền tải dữ liệu ứng dụng của bạn qua mạng hiệu quả hơn. Nắm vững các nguyên tắc sẽ giúp bạn xây dựng ứng dụng Java mạnh mẽ và an toàn hơn.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào