middle
Как изменить стандартное поведение сериализации/десериализации?
Существует два подхода: реализация Externalizable для полного контроля или определение специальных методов в Serializable-классе для точечной кастомизации.
Подход 1: интерфейс Externalizable
Позволяет полностью описать логику сериализации и десериализации вручную. Во время десериализации вызывается конструктор без параметров, затем на созданном объекте вызывается readExternal.
Пример
public class User implements Externalizable {
private String name;
private int age;
public User() {} // Обязателен для Externalizable
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(name);
out.writeInt(age);
}
@Override
public void readExternal(ObjectInput in) throws IOException {
this.name = in.readUTF();
this.age = in.readInt();
}
}
Подход 2: специальные методы в Serializable-классе
Если у класса определены следующие методы, механизм сериализации использует их вместо поведения по умолчанию:
| Метод | Назначение |
|---|---|
private void writeObject(ObjectOutputStream out) |
Запись объекта в поток |
private void readObject(ObjectInputStream in) |
Чтение объекта из потока |
Object writeReplace() |
Подмена объекта перед записью (возвращает замещающий объект) |
Object readResolve() |
Подмена объекта после чтения (возвращает замещающий объект) |
Сравнение подходов
| Критерий | Serializable + методы | Externalizable |
|---|---|---|
| Конструктор при десериализации | Не вызывается | Вызывается (без параметров) |
| Контроль | Частичный (можно дополнить стандартный) | Полный |
| Объём кода | Меньше (по необходимости) | Больше (все поля вручную) |
final-поля |
Поддерживаются | Не поддерживаются (нельзя задать после конструктора) |
На собеседовании: назовите оба подхода и подчеркните разницу в вызове конструктора. Упоминание
writeReplace/readResolve— сильный плюс, особенно в контексте Singleton-паттерна.