junior
Опишите процесс сериализации/десериализации с использованием Serializable
При использовании Serializable JVM применяет алгоритм сериализации, который через Reflection API автоматически записывает состояние объекта в поток байтов.
Алгоритм сериализации
- Запись метаданных о классе — имя класса,
serialVersionUID, идентификаторы полей - Рекурсивная запись описания суперклассов вплоть до
java.lang.Object(не включительно) - Запись примитивных значений полей, начиная с полей самого верхнего суперкласса
- Рекурсивная запись объектов, являющихся полями сериализуемого объекта
Ранее сериализованные объекты повторно не записываются — это позволяет корректно обрабатывать циклические ссылки и граф объектов.
Алгоритм десериализации
- Под объект выделяется память
- Поля заполняются значениями из потока
- Конструктор сериализуемого класса не вызывается
- Вызывается конструктор без параметров ближайшего несериализуемого родительского класса
Если у несериализуемого суперкласса нет конструктора без параметров, при десериализации будет выброшено InvalidClassException.
Пример сериализации/десериализации
import java.io.*;
public class SerializationExample {
public static void main(String[] args) throws Exception {
User user = new User("Иван", 30);
// Сериализация
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("user.ser"))) {
oos.writeObject(user);
}
// Десериализация
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("user.ser"))) {
User restored = (User) ois.readObject();
System.out.println(restored); // User{name='Иван', age=30}
}
}
}
class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// getters, toString...
}
Частые ошибки
- Ожидание вызова конструктора при десериализации — конструктор сериализуемого класса не вызывается, поэтому логика инициализации в нём не выполнится
- Отсутствие
Serializableу вложенных объектов — если поле класса не реализуетSerializableи не помеченоtransient, будетNotSerializableException - Забыть про суперкласс — если родитель не
Serializable, его поля не сохраняются, а при десериализации инициализируются через конструктор по умолчанию
На собеседовании: ключевой момент — конструктор не вызывается при десериализации
Serializable-объекта, но вызывается конструктор без параметров у несериализуемого суперкласса. Это частый вопрос-ловушка.