Trong Java, Serializable là một interface trong gói java.io, cho phép một đối tượng được lưu trữ (serialize) hoặc đọc ra (deserialize) dưới dạng nhị phân.
Serialization là quá trình chuyển đổi một đối tượng trong Java thành một dãy nhị phân, có thể được ghi vào một file hoặc gửi qua mạng. Deserialization là quá trình ngược lại, chuyển đổi dãy nhị phân thành một đối tượng Java.
Các bài viết liên quan:
Để một đối tượng có thể được serialize, nó cần phải implements Serializable interface.
Ví dụ:
import java.io.Serializable; class MyClass implements Serializable { private static final long serialVersionUID = 1L; private int data; public MyClass(int data) { this.data = data; } public int getData() { return data; } }
Sau khi một đối tượng được implement Serializable, chúng ta có thể sử dụng các lớp ObjectOutputStream và ObjectInputStream để serialize và deserialize các đối tượng của chúng ta.
Chú ý: có một số trường hợp một đối tượng không cần thiết phải được serialize vì một số lý do bảo mật, hoặc vì nó chứa các tham chiếu đến đối tượng khác mà không thể serialize được. Trong trường hợp đó, chúng ta có thể sử dụng từ khóa transient để chú thích các trường không cần thiết phải được serialize.
Ví dụ:
class MyClass implements Serializable { private static final long serialVersionUID = 1L; private transient int data; public MyClass(int data) { this.data = data; } public int getData() { return data; } }
Trong ví dụ trên, trường data được chú thích với từ khóa transient, nên nó sẽ không được serialize khi chúng ta ghi ra file hoặc gửi qua mạng.
Serialization là một tính năng mạnh mẽ trong Java, cho phép chúng ta lưu trữ và truyền đối tượng qua mạng hoặc lưu trữ trạng thái của chúng trong bộ nhớ. Nhưng cũng cần chú ý đến vấn đề bảo mật và tối ưu hóa khi sử dụng chức năng này.
khi nào nên sử dung serializable trong java
Trong Java, serialization là một tính năng mạnh mẽ cho phép chúng ta lưu trữ và truyền đối tượng qua mạng hoặc lưu trữ trạng thái của chúng trong bộ nhớ. Do đó, có những trường hợp mà sử dụng serialization là cần thiết:
- Lưu trữ trạng thái đối tượng: Khi chúng ta muốn lưu trữ trạng thái của một đối tượng vào bộ nhớ hoặc file để sử dụng lại sau này, chúng ta có thể sử dụng serialization để làm điều này.
- Truyền đối tượng qua mạng: Khi chúng ta muốn truyền một đối tượng qua mạng, chúng ta có thể chuyển đổi nó thành dãy nhị phân và gửi nó qua mạng, sau đó chuyển nó trở lại thành đối tượng bằng deserialization.
Nhưng cũng cần lưu ý đến việc an toàn và bảo mật, đặc biệt khi truyền đối tượng qua mạng, chúng ta cần xác định xem các trường của đối tượng có cần thiết phải được gửi qua mạng hay không, và sử dụng các cơ chế bảo mật tương ứng để bảo vệ thông tin trong đối tượng khi truyền qua mạng.
Còn trong trường hợp lưu trữ trạng thái đối tượng, chúng ta cần chú ý đến việc cập nhật serialVersionUID để tránh việc lỗi khi deserialize đối tượng vì thay đổi trong class, hoặc sử dụng kỹ thuật externalizable để tùy biến việc serialize theo nhu cầu của chúng ta
Serialization là một chức năng mạnh mẽ trong Java cho phép chúng ta lưu trữ và truyền đối tượng qua mạng hoặc lưu trữ trạng thái của chúng trong bộ nhớ. Nhưng cũng cần chú ý đến việc an toàn và bảo mật khi sử dụng chức năng này, đặc biệt là trong trường hợp truyền đối tượng qua mạng. Các kỹ thuật bảo mật phù hợp, chẳng hạn như mã hóa dữ liệu, cần được sử dụng để bảo vệ thông tin trong đối tượng.
Việc lưu trữ trạng thái đối tượng bằng cách sử dụng serialization cũng cần được cẩn thận với việc cập nhật serialVersionUID, hoặc sử dụng Externalizable để tùy biến việc serialize theo nhu cầu.
Ngoài ra, cũng cần lưu ý đến việc tối ưu hóa serialization với việc sử dụng các thuật toán nhẹ hơn, chẳng hạn như serialization với trạng thái mặc định hoặc sử dụng các thư viện nhị phân tối ưu hơn, chẳng hạn như protobuf hoặc Avro, để giảm thiểu kích thước dữ liệu được lưu trữ và truyền qua mạng.
Với việc lưu trữ trạng thái đối tượng, serialization có thể được sử dụng để lưu trữ và truy xuất lại trạng thái của đối tượng sau một thời gian dài.
Trong trường hợp truyền đối tượng qua mạng, chúng ta có thể sử dụng serialization để chuyển đổi đối tượng thành dữ liệu nhị phân và gửi nó qua mạng, sau đó chuyển nó trở lại thành đối tượng bằng deserialization.
Trong tổng quát, việc sử dụng serialization trong Java cần được tối ưu hóa với việc bảo mật và tối ưu hóa, để có thể sử dụng hiệu quả và an toàn.
Một vài ví dụ về serializable trong java
Trong Java, để một lớp có thể được serializable, nó phải thừa kế từ lớp Serializable
hoặc Externalizable
. Các lớp được serializable có thể được lưu trữ trong dạng nhị phân hoặc được gửi qua mạng.
Ví dụ:
import java.io.Serializable; public class Person implements Serializable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
import java.io.*; public class SerializationExample { public static void main(String[] args) { Person person = new Person("John Doe", 30); try { FileOutputStream fileOut = new FileOutputStream("person.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(person); out.close(); fileOut.close(); System.out.println("Serialized data is saved in person.ser"); } catch (IOException i) { i.printStackTrace(); } } }
import java.io.*; public class DeserializationExample { public static void main(String[] args) { Person person = null; try { FileInputStream fileIn = new FileInputStream("person.ser"); ObjectInputStream in = new ObjectInputStream(fileIn); person = (Person) in.readObject(); in.close(); fileIn.close(); } catch (IOException i) { i.printStackTrace(); return; } catch (ClassNotFoundException c) { System.out.println("Person class not found"); c.printStackTrace(); return; } System.out.println("Deserialized Person..."); System.out.println("Name: " + person.getName()); System.out.println("Age: " + person.getAge()); } }
Đoạn code trên mô tả việc Serialization và Deserialization lớp Person, thông qua việc sử dụng ObjectInputStream và ObjectOutputStream.
Ví dụ stream trong java
Ví dụ sau minh họa việc đọc dữ liệu từ một tập tin với sử dụng InputStream:
import java.io.FileInputStream; import java.io.IOException; public class FileInputStreamExample { public static void main(String[] args) { try { FileInputStream fileIn = new FileInputStream("data.txt"); int data; while((data = fileIn.read()) != -1) { System.out.print((char)data); } fileIn.close(); } catch (IOException e) { e.printStackTrace(); } } }
Trong ví dụ trên, chúng ta tạo một đối tượng FileInputStream với tên tập tin “data.txt”. Sau đó, sử dụng phương thức read() để đọc từng byte dữ liệu từ tập tin và in ra màn hình. Cuối cùng, gọi phương thức close() để đóng luồng.
Ví dụ sau minh họa việc ghi dữ liệu vào một tập tin với sử dụng OutputStream:
import java.io.FileOutputStream; import java.io.IOException; public class FileOutputStreamExample { public static void main(String[] args) { try { FileOutputStream fileOut = new FileOutputStream("output.txt"); String message = "This is a message being written to the file"; byte[] bytes = message.getBytes(); fileOut.write(bytes); fileOut.close(); System.out.println("The message was written to the file!"); } catch (IOException e) { e.printStackTrace(); } } }
Trong ví dụ trên, chúng ta tạo một đối tượng FileOutputStream với tên tập tin “output.txt”. Sau đó, chuyển đổi chuỗi thông điệp thành mảng byte và gọi phương thức write(bytes) để ghi dữ liệu vào tập tin. Cuối cùng, gọi phương thức close() để đóng luồng và in ra màn hình thông báo “The message was written to the file!”.
Có nhiều loại Stream khác nhau như Reader, Writer, BufferedReader, BufferedWriter cũng có thể được sử dụng để đọc và ghi dữ liệu, tùy vào mục đích sử dụng.
Còn có các stream dành riêng cho việc đọc ghi dữ liệu object, hoặc xử lý dữ liệu mã hóa/ giải mã.
Cách sử dụng các loại stream khác nhau có thể khác nhau, nhưng các bước tạo và đóng luồng là tương tự nhau.