Сериализация Java

Сериализация Java — это процесс преобразования объекта в поток байтов, чтобы объект можно было сохранить на диск, передать по сети или сохранить в памяти, а затем десериализовать, чтобы преобразовать поток байтов обратно в объект.

В Java сериализация реализуется черезjava.io.Serializableинтерфейс. Этот интерфейс не имеет методов; это просто интерфейс-маркер, используемый для указания, что класс может быть сериализован.

Когда вы сериализуете объект, вы помещаете его в специальный файл, который можно сохранить, передать или хранить. Десериализация, с другой стороны, открывает этот файл, читает сериализованные данные, а затем восстанавливает их в объект для использования в программе.

Сериализация — это метод сохранения, передачи и восстановления объектов. Она позволяет перемещать объекты и обмениваться ими между разными компьютерами, что очень полезно для распределённых систем, хранения данных и кроссплатформенной коммуникации.

Ниже приведены основные понятия и применение сериализации Java:

Реализация интерфейса Serializable: чтобы сделать класс сериализуемым, нужно, чтобы класс реализовывал интерфейс java.io.Serializable. Это сообщает компилятору Java, что класс может быть сериализован, например:

Пример

import java.io.Serializable;

public class MyClass implements Serializable {
    // члены и методы класса
}

Сериализация объекта:Используйте класс ObjectOutputStream, чтобы сериализовать объект в поток байтов. Ниже приведён простой пример:

Пример

MyClass obj = new MyClass();
try {
    FileOutputStream fileOut = new FileOutputStream("object.ser");
    ObjectOutputStream out = new ObjectOutputStream(fileOut);
    out.writeObject(obj);
    out.close();
    fileOut.close();
} catch (IOException e) {
    e.printStackTrace();
}

Приведённый выше код сериализует объект obj в файл с именем "object.ser".

Десериализация объекта:Используйте класс ObjectInputStream для десериализации объекта из потока байтов. Ниже приведён простой пример:

Пример

MyClass obj = null;
try {
    FileInputStream fileIn = new FileInputStream("object.ser");
    ObjectInputStream in = new ObjectInputStream(fileIn);
    obj = (MyClass) in.readObject();
    in.close();
    fileIn.close();
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

Приведённый выше код считывает поток байтов из файла "object.ser" и десериализует его в объект MyClass.

Классы ObjectInputStream и ObjectOutputStream — это высокоуровневые потоки данных, которые содержат методы для десериализации и сериализации объектов.

Класс ObjectOutputStream содержит множество методов записи для записи различных типов данных, но есть один особый метод, который является исключением:

public final void writeObject(Object x) throws IOException

Приведённый выше метод сериализует объект и отправляет его в выходной поток. Аналогично, класс ObjectInputStream содержит следующий метод для десериализации объекта:

public final Object readObject() throws IOException, ClassNotFoundException

Этот метод извлекает следующий объект из потока и десериализует объект. Его возвращаемое значение — Object, поэтому вам нужно привести его к соответствующему типу данных.

Пример

Чтобы продемонстрировать, как работает сериализация в Java, я буду использовать класс Employee, упомянутый в предыдущем учебном пособии. Предположим, мы определяем класс Employee следующим образом; этот класс реализует интерфейс Serializable.

Код файла Employee.java:

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("Отправка чека для " + name + " " + address); } }

Обратите внимание, что для успешной сериализации объекта класса должны быть выполнены два условия:

Класс должен реализовывать интерфейс java.io.Serializable.

Все свойства класса должны быть сериализуемыми. Если свойство несериализуемо, оно должно быть помечено как transient.

Если вы хотите узнать, является ли стандартный класс Java сериализуемым, проверьте документацию для этого класса. Очень просто проверить, можно ли сериализовать экземпляр класса; вам просто нужно проверить, реализует ли класс интерфейс java.io.Serializable.


Сериализация объекта

Класс ObjectOutputStream используется для сериализации объекта. Пример SerializeDemo ниже создает экземпляр объекта Employee и сериализует этот объект в файл.

После выполнения программы создается файл с именем employee.ser. Программа не выдает никаких выходных данных, но вы можете понять, что делает программа, изучив код.

Примечание:При сериализации объекта в файл стандартное соглашение Java — давать файлу расширение .ser.

Код файла SerializeDemo.java:

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("Сериализованные данные сохранены в /tmp/employee.ser"); }catch(IOException i) { i.printStackTrace(); } } }

Десериализация объекта

Программа DeserializeDemo, приведенная ниже, демонстрирует десериализацию, при этом в /tmp/employee.ser хранится объект Employee.

Код файла DeserializeDemo.java:

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 не найден"); c.printStackTrace(); return; } System.out.println("Десериализованный Employee..."); System.out.println("Имя: " + e.name); System.out.println("Адрес: " + e.address); System.out.println("SSN: " + e.SSN); System.out.println("Номер: " + e.number); } }

Результат компиляции и выполнения вышеприведённой программы выглядит следующим образом:

Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101

Ниже приведены ключевые моменты, на которые следует обратить внимание:

Блок try/catch в методе readObject() пытается перехватить исключение ClassNotFoundException. Чтобы JVM могла десериализовать объект, она должна иметь возможность найти класс для байт-кода. Если JVM не может найти класс во время десериализации объекта, она выбрасывает исключение ClassNotFoundException.

Обратите внимание, что возвращаемое значение метода readObject() приводится к ссылке на Employee.

Когда объект сериализуется, значение свойства SSN равно 111222333, но поскольку это свойство является transient, значение не отправляется в выходной поток. Поэтому после десериализации свойство SSN объекта Employee равно 0.

Другие расширения