Gymterview
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-паттерна.