Там хорошее описание в последнем разделе Джоша Блоха Эффективное Java, второе издание.
Предположим, что у вас есть класс A, который вы хотите сделать сериализуемым. Сначала вы объявите его для реализации Serializable. Затем вы используете метод сериализации writeReplace(), чтобы вернуть так называемый "прокси-сервер сериализации", который будет сериализован вместо экземпляра A. Метод writeReplace() не должен быть общедоступным. Сериализация по умолчанию на A никогда не запускается, поэтому все свойства API A могут поддерживаться.
Как правило, прокси реализуется как частный статический вложенный класс, который сам должен реализовать Serializable (или Externalizable для полного контроля процесса чтения/записи). Поскольку прокси-сервер является закрытым, его детали реализации, такие как наличие конструктора no-arg и возможность его изменения, будут скрыты.
Прокси хранит достаточно состояния исходного объекта для записи, чтобы он мог восстановить объект при десериализации. При десериализации прокси использует метод readResolve() для возврата экземпляра A. Для синглетонов это может быть одиночный экземпляр.