Сериализация и рефлексия
Сериализация и рефлексия решают, на первый взгляд, разные задачи, но обе про одно — про пересечение границы между живым объектом в памяти и чем-то за её пределами. Сериализация превращает состояние объекта в байтовый поток, который можно сохранить на диск или отправить по сети, а потом восстановить обратно. Рефлексия даёт коду заглянуть в устройство класса во время выполнения — перечислить его поля и методы и обратиться к ним по имени, даже если компилятор об этих типах ничего не знал.
Именно на этих двух механизмах держится «магия» фреймворков: DI-контейнеры создают объекты по имени класса, ORM раскладывают строку таблицы по полям сущности, сериализаторы сохраняют произвольные объекты. Цена — обе возможности обходят обычные гарантии: сериализация игнорирует конструктор и исключает transient/static-поля, рефлексия пробивает инкапсуляцию и переносит ошибки на время выполнения. Полная карта — в слоях ниже.
Карта темы
- Сериализация — маркерный интерфейс
Serializable,serialVersionUID, граф объектов и что не попадает в поток. - Ключевое слово transient — поля, исключаемые из сериализации, и почему они возвращаются пустыми.
- Reflection API — объект
Class, интроспекция во время выполнения и цена гибкости.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Забыть явный serialVersionUID | Автогенерированный сдвигается при любом изменении класса — при чтении старого потока летит InvalidClassException |
| Считать, что сериализуются все поля | transient и static в поток не попадают |
| Ждать вызова конструктора при десериализации | Для Serializable-класса конструктор не вызывается — объект собирается в обход него |
Полагать, что transient-поле сохранит значение | После чтения оно получает значение по умолчанию для типа (null / 0 / false) |
Ссылаться на не-Serializable объект из сериализуемого | NotSerializableException в момент записи |
| Применять рефлексию в горячем цикле | Она заметно медленнее прямого вызова метода |
Лезть к private через рефлексию без setAccessible(true) | IllegalAccessException; а система модулей (JPMS) может запретить и это |
Значение для собеседований
Тему спрашивают реже, чем коллекции или многопоточность, но она хорошо проверяет глубину: понимаете ли вы, что сериализация — это про байты и совместимость версий, а не про JSON, и где рефлексия оправдана, а где это оверинжиниринг.
Что обычно проверяют:
- Что делает
Serializableи какserialVersionUIDвлияет на совместимость версий. - Какие поля не сериализуются (
transient,static) и вызывается ли при чтении конструктор. - Что такое рефлексия, через какой объект она работает (
Class) и какие у неё издержки. - Где рефлексия действительно нужна (фреймворки), а где хватит обычного полиморфизма.
Типичный неверный ответ: «сериализация — это просто перевод объекта в JSON». Это открывает разговор о том, что встроенная сериализация Java пишет бинарный формат, тащит весь граф достижимых объектов, обходит конструктор — и именно поэтому считается угрозой безопасности при чтении недоверенных данных.