Решая задачу task2018, заметил следующее: сериализация и десериализация искажают данные наследуемого поля, если:
1. либо не пометить класс-предок как Serializable;
1. либо не написать в сериализуемом классе-потомке собственных реализаций методов writeObject и readObject.
---
так вот вопросы:
1. Почему джава успешно сериализует и десериализует (без Exceptions), но при этом искажает данные, если не проделать что-то из вышенаписанного?
2. Почему эти методы нужно писать, и кто их вызывает, если они написаны у класса-потомка, но в методе main у объектов этого класса эти методы никто и ничто не вызывает. (Одноименные методы вызываются лишь у соответствующих потоков ObjectOutputStream и ObjectInputStream, но не у объектов класса, которые в данный поток следует передать)
Причем, эти методы не являются переопределенными - при написании аннотации @Override - подчеркивается красным.
3. Как и почему это вообще работает???
4. Перед последними двумя попытками отправить на проверку Ментор подсказывал
"В методе writeObject должен быть вызван метод defaultWriteObject на объекте полученном в качестве параметра."
"В методе readObject должен быть вызван метод defaultReadObject на объекте полученном в качестве параметра."
Собственно, я-то эти вызовы добавил, но что они дали? До этого ведь успешно пропускало, и вывод на экран соответствовал ожидаемому.
---
Решение не прикрепляю, т.к. оно у меня все же зачлось. Но, думаю, у всех, кто решил, оно и так стандартное.
Griboed
30 уровень
Объясните про сериализацию, пожалуйста - в лекциях не нашел нужной информации.
Решен
Комментарии (3)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Денис Enterprise Java Developer
22 февраля 2023, 10:50решение
Еще бы ты код приложил, цены бы тебе не было, а то гадание на кофейной гуще не совсем мой профиль.
Так могу ответить только общими фразами из серии "работает потому, что синтаксически это верно, а ответственность за целостность данных несёт разработчик, ведь Java и не может и не должна думать за него"
Интерфейс Serializable это просто маркер который уведомляет Java машину, что этот класс можно сериализовать и разработчик сделал всё от него зависимое для достижения результата. Если ты сделал не всё... это не проблемы Java машины :)
А вот что до методов writeObject / readObject и прочих - тут нужно просто открывать доки и смотреть как работает непосредственно механизм сериализации. То что они не оверрайдят ничего вовсе не значит, что они не нужны для корректной работы.
В частности, если открыть всё тот же интерфейс Serializable там вполне неплохая джавадока написана по этому поводу. Вот например ответ на твой первый вопрос оттуда:
It is possible for subtypes of non-serializable classes to be serialized and deserialized. During serialization, no data will be written for the fields of non-serializable superclasses. During deserialization, the fields of non-serializable superclasses will be initialized using the no-arg constructor of the first (bottommost) non-serializable superclass. ну и там дальше еще пару абзацев)
А вот начало ответа на второй:
Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
Как именно это работает - другой вопрос. Методы приватные, потому и не вынесены в интерфейс, скорее всего вызываются посредством рефлексии.
+2
Griboed
22 февраля 2023, 12:07
Спасибо, я все понял! Оказывается, поле, унаследованное от несериализованного суперкласса вовсе не сериализовалось, а при десериализации, оно просто инициировалось дефолтным значением, прописанным в суперклассе.
Вот, кстати, код:
А для чего нужны object.defaultWriteObject(); и object.defaultReadObject()?
0
Денис Enterprise Java Developer
22 февраля 2023, 12:11полезный
Исходя из названия default могу предположить что это реализация по умолчанию :) На случай если ты соберешься заниматься сериализацией без дополнительной логики. Что в твоём коде и происходит. Подозреваю что методы ты мог вообще не реализовывать, ведь никакой логики там сейчас нет кроме дефолтной, но лучше с этим поведением поиграться отдельно.
+1