Serialization là một khái niệm giúp chúng ta có thể chuyển đổi trạng thái của một Java object thành một định dạng nào đó để Java object này có thể được lưu trữ ở đâu đó và sau đó, nó sẽ được sử dụng bởi một tiến trình khác.
Thông thường, khi sử dụng Serialization, Java object của chúng ta sẽ được chuyển đổi qua byte streams và chúng ta có thể lưu byte stream này trong bộ nhớ, trên ổ đĩa, truyền qua mạng đến một server nào đó hoặc cũng có thể lưu chúng vào database.
Và khi một tiến trình khác sử dụng một Java object đã được Serialization, nó sẽ chuyển đổi định dạng đã Serialization về trạng thái của Java object ban đầu. Nhờ vậy, tiến trình đó có thể sử dụng lại Java object của chúng ta.
Để cho một object có thể sử dụng Serialization được, chúng ta phải cho object của chúng ta hiện thực một interface với tên gọi là java.io.Serializable. Interface này không có bất kỳ một phương thức nào cần hiện thực cả các bạn ạ!
Để các bạn có thể hiểu rõ hơn, mình sẽ làm một ví dụ để minh chứng những điều mình vừa nói nhé!
Ví dụ ở đây, mình có một đối tượng là Student:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.huongdanjava.javaexample; public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } |
Vì mình muốn sử dụng Serialization nên mình sẽ hiện thực interface Serializable cho đối tượng Student như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.huongdanjava.javaexample; import java.io.Serializable; public class Student implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } |
Như các bạn thấy, mình đã thêm một biến tên là serialVersionUID trong object Student của mình. Mục đích của biến này là để chắc chắn trước và sau khi chuyển đổi, lớp Student của chúng ta là một đấy các bạn.
OK, bây giờ chúng ta sẽ viết code để chuyển đổi đối tượng Student và lưu byte streams của nó vào một tập tin nào đó xem thử nhé!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.huongdanjava.javaexample; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class SerializationExample { public static void main(String[] args) { // Create Student object Student student = new Student(); student.setName("Khanh"); student.setAge(30); // Use FileOutputStream to save the Student object into a file try ( FileOutputStream fos = new FileOutputStream("E:\\student.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); ) { oos.writeObject(student); } catch (IOException i) { i.printStackTrace(); } } } |
Bây giờ, một tập tin đã được tạo và nếu bạn kiểm tra tập tin mà bạn đã lưu đối tượng Student của chúng ta, bạn sẽ thấy nội dung giống giống như sau:
1 |
’ sr &com.huongdanjava.javaexample.Student I ageL namet Ljava/lang/String;xp t Khanh |
Vậy làm thế nào để tiến trình khác có thể sử dụng tập tin mình đã tạo trong ví dụ trên để sử dụng, chúng ta viết code tiếp nhé!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.huongdanjava.javaexample; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class DeserializationExample { public static void main(String[] args) { Student student = null; try ( FileInputStream fos = new FileInputStream("E:\\student.txt"); ObjectInputStream oos = new ObjectInputStream(fos); ) { student = (Student) oos.readObject(); } catch (IOException i) { i.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.err.println(student.getName()); System.err.println(student.getAge()); } } |
Kết quả:
1 2 |
Khanh 30 |
Như bạn thấy trước và sau khi chuyển đổi, đối tượng Student của mình vẫn có những thông tin mà chúng ta đã lưu trước đó.
Xe Ôm
Bài viết cung cấp cái nhìn tổng quan cho các bạn mới học Java.
Cũng không có nhiều website/blog cho các bạn học Java tham khảo bằng tiết Việt, cảm ơn sự nỗ lực của bạn Khanh rất nhiều.
Mình xin bổ sung một vài ý nếu như bạn muốn bài viết của mình rõ ràng và chính xác hơn.
Hầu hết đều đã được đề cập trong java docs của Serializable này
Mình lấy của Jdk 1.7 làm ví dụ: https://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
+/ Trong ví dụ, việc class được serialize/deserialze thành công là do bản thân class cùng với các field (String, int) default đã được implement Serializable rồi, Và Java sẽ tự động xử lý việc này. Nếu không sẽ có lỗi lúc serialize/deseriaize
+/ Việc specific 1 biến
serialVersionUID
nhằm để xác nhận lại object lúc gửi/nhận tương thích với quá trình serialization.> The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender’s class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named “serialVersionUID” that must be static, final, and of type long
Khanh Nguyen
Cảm ơn bạn đã góp ý!
Trong bài viết, mình cũng đã đề cập đến việc sử dụng biến serialVersionUID có tác dụng gì rồi. Chắc nó không được chi tiết hả bạn?
Sẵn tiện, bạn có thể trao đổi với mình thêm về các vấn đề của Java ở đây nhé https://javavietnamforum.org/
Xe Ôm
Cảm ơn bạn đã nhắc nhở, chắc mình bỏ sót phần đó, vì trong phần comment có bạn hỏi về cái version này.
Về phần forums thì mình ngại đăng ký 😀
Anw, đi comment dạo này cũng hay 🙂
nguyenvannam
tks admin nhé
namnguyen
bài viết rất hay ạ, cám ơn anh.
có điều em chưa tường minh được dòng này
private static final long serialVersionUID
mong được chỉ giáo ạ
An
anh co the giai thich khi nao minh nen dung Serializable khong
va no thuong ung dung trong truong hop nao?.
thank anh.
Nguyen Van Linh
Em chào anh, a có thể chỉ cho e cách ghi file mà trong đối tượng chứa 1 đối tượng khá không ạ
ví dụ như là class này ạ e cám ơn
public class Student{
private String name;
private int age;
private Address address;
}
Khanh Nguyen
Em đã thử implement interface Serialization cho cả class Address và Student rồi làm theo ví dụ ghi file của anh chưa?
Triet Truong
Nếu bạn dùng IntelliJ IDE có cài SonarLint plugin thì ở trường hợp này, SonarLint sẽ đưa ra cảnh báo đối với field address:
Fields in a “Serializable” class should either be transient or serializable. (https://rules.sonarsource.com/java/RSPEC-1948)
Khi serialize Student thì field Address có thể được serialize theo (nếu class Address implement Serializable) hoặc không (đặt private transient Address address).
Dzung
anh có thể giải thích dùm em cú pháp (Student) được thêm vào hàng bên dưới này có ý nghĩa là gì được không ạ? Chỗ này em chưa hiểu lắm. Em cảm ơn ạ!
student = (Student) oos.readObject();
Khanh Nguyen
À, cái này là đoạn code sẽ đưa cái Object lấy được từ phương thức readObject() về đối tượng Student đó em. Còn gọi là cast đối tượng.
Em nên tìm tòi thêm những kiến thức Java cơ bản nhé!