Интерфейс Serializable пуст, но есть ряд методов, добавив которые в сериализуемый класс можно добиться изменения этапов процесса сериализации и десериализации.

readObjectNoData() используется для инициализации класса-родителя, который при сериализации оригинального объекта еще не был родителем. Подробное объяснение.

readObject(ObjectInputStream s) переопределяет стандартную десериализацию.

Методы readObject* похожи на конструктор. Как и конструктор, они подвержены проблеме виртуального вызова. Как и конструктор, они используются для поддержания инвариантов класса (только для случая десериализации).

writeObject(ObjectOutputStream s) используется для записи собственной сериализационной формы.

Object readResolve() может использоваться для реализации какого-либо порождающего паттерна при десериализации. Даже при его использовании объект сначала будет десериализован, поэтому рекомендуется вместе с этим методом помечать все поля transient. Видимость этого метода для наследника определяет, будет ли наследник вызывать его.

Для подмены объекта при записи добавляется симметричный метод Object writeReplace().

Интерфейс Externalizable дает инструмент полной подмены реализации сериализации. Рассмотрим его в следующих постах.