Сериализация

Pataasin ang iyong marka sa homework at exams ngayon gamit ang Quizwiz!

Что такое сериализация и десериализация?

Сериализация - это процесс сохранения состояния объекта в последовательность байт. Десериализация - это процесс восстановления объекта из этих байт.

Что нужно сделать, чтобы ДЕсериализовать объект?

1) Класс объекта должен реализовывать интерфейс Serializable 2) Создать поток *ObjectInputStream* (ois), в который передать *InputStream* (instream) (из файла, из памяти...) 3) Получить объект и привести к нужному типу: MyObject my = (MyObject) *ois.readObject*(instream)

Какие объекты и методы используются при сериализации и де-сериализации в Java?

1) Интерфейс Serializable: void java.io.ObjectOutputStream.*writeObject*(object) Object java.io.ObjectInputStream.*readObject*() Также есть методы ручного чтения примитивных полей: readInt(), readFloat, writeByte и т.д. 2) Интерфейс Externalizable: void java.io.Externalizable.*readExternal*(ObjectInputStream in) void java.io.Externalizable.*writeExternal*(ObjectOutputStream out)

Чем отличаются интерфейсы Serializable и Externalizable?

1) Externalizable extends Serializable 2) Интерфейс Serializable полностью реализует виртуальная машина JVM. 3) Интерфейс Externalizable имеет методы writeExternal() и readExternal(), которые позволяют вручную указать - какие поля записывать. Это может в том числе повысит производительность.

Что такое serialVersionUID? Как он указывается? Что если его не определить?

1) SerialVersionUID - это "штамп" или код, который присваивается объекту при сериализации. Этот штамп позволяет отслеживать "версию" класса или объекта, который сериализуется или десериализуется. 2) Указывается в классе: *private static final long serialVersionId = ... * 3) Если SerialVersionId не задать явно, то при малейшем изменении класса (переименовали поле) оно изменится. 4) Если объект был сериализован, то теперь его не восстановить: его serialVersionId будет отличаться от сохраненного. Метод readObject() в этом случае только выдаст java.io.InvalidClassException.

Чем отличаются методы восстановления объекта в интерфейсах Serializable и Externalizable?

1) Serializible не использует конструктор объекта - он просто восстанавливает его полностью из последовательности байтов. 2.1) Externalizible вначале вызывает public конструктор объекта без параметров, а затем наполняет поля объекта значениями. 2.2) Если у класса не будет public конструктора без параметров, при попытке десериализовать объект выпадет java.io.InvalidClassException.

Какие поля в классе Java не сериализуются?

1) static поля - они часть класса, а не объекта. Следовательно, они не указывают на состояние объекта. 2) transient поля - модификатор как раз и говорит о том, что "это поле не отмечает состояние объекта". Следовательно, его не нужно сериализовать.

Что будет, если у нас класс Serializable, а его класс-родитель - нет?

1) В случае, если в цепочке классов (child -> parent -> grandparent) какой-то из них не Serializable, то он инициализируется *public конструктором без параметров*. 2) Даже если выше не-Serializable класса другие классы Serializable, это уже не важно - дальше создание идет просто по цепочке конструкторов. 3) Если в цепочке у какого-то класса не окажется конструктора без параметров - вылезет *java.io.InvalidClassException* с сообщением "no valid constructor".

А что если у нас Serializable класс содержит поля, в которых объекты не Serializable?

1) В таком случае код *скомпилируется*. 2) Но *в рантайме* при попытке сериализации , когда мы дойдем до этого поля и объекта, мы получим *NotSerializableException*.

Можно ли передавать сериализованный объект по сети интернет?

1) Да, сериализованный объект - это просто набор байтов. 2) Его спокойно можно передать по сети и в другом месте восстановить объект. 3) Также объект можно хранить в таком виде в базе данных или в файле.

Зачем вообще нужна сериализация?

1) Данные в памяти "живут", до момента завершения приложения. Сериализация позволяет записать объекты в файлы и, таким образом, восстановить их затем. 2) Сериализация предоставляет универсальный механизм обмена данными между компонентами приложения или узлами в интернете.

(Сериализация) Если у нас несколько объектов и мы хотим их сохранить в один файл - что мы делаем?

1) Делаем один FileOutputStream == fos 2) Оборачиваем его в ObjectOutputStream(fos) == oos 3) Пишем: oos.writeObject(object1); oos.writeObject(object2); ... oos.flush(); oos.close(); 4) Когда читаем объекты методом ObjectInputStream.readObject(), то получаем их в том же порядке, как они записаны.

Мы хотим, чтобы при сериализации значения некоторых полей не сохранялись. Как этого достичь?

1) Добавить к полю модификатор transient. В таком случае после восстановления его значение будет null. 2) Сделать поле static. Значения статических полей автоматически не сохраняются. Впрочем, это можно сделать вручную: ObjectOutputStream oos = new ...; oos.writeInt(obj.staticField1); oos.writeObject(a); 3) Также можно написать свои методы read/writeObject или read/writeExternal и записать в них только те поля, которые нам нужны.

Что за интерфейс Serializable?

1) Интерфейс java.io.Serializable - это интерфейс-маркер, в нем нет методов. 2) Если класс реализует интерфейс, это говорит сериализующему механизму, что этот класс можно сериализовать.

Вы взяли класс и сериализовали его объект. Затем вы добавили новое поле в классе. После чего - пытаетесь десериализовать объект. Что произойдет?

1) Если в классе не был указан serialVersionUID, то выпадет InvalidClassException, поскольку у класса он поменяется. 2) Если же был объявлен - объект восстановится. При этом восстановит значения в поля, что были до сериализации восстановятся, а новые инициализируются как 0, null и т.д.

Перечислит шаги, которые выполняет механизм сериализации при сериализации объекта (что за чем записывается в поток)

1) Запись метаданных: указание, что это сериализация, версия сериализации, указание "сейчас начнется объект". 2.1) Запись рекурсивно данных о классе объекта *"снизу вверх"*: класс -> super -> supersuper и т.д пока не будет достигнут java.lang.Object. *Сам класс Object не пишется.* 2.2) При описании пишется имя класса, имена и тип его полей, примитивных и ссылок. Для ссылок просто указывается, что "там объект", без описания класса. 3.1) Запись значений данных в экземпляре, *"сверху вниз"*: parent -> sub -> subsub... 3.2) Если поле - ссылка на объект, то рекурсивно идет запись объекта: описания полей "снизу вверх", затем написание значений "сверху вниз".

Что будет с работой интерфейсов Serizalizable и Externalizable в случае, если переменная - final?

1) Интерфейс Serializable отработает без проблем - он использует рефлексию для создания объекта. При этом используются методы ObjectInputStream.defaultReadObject() и ObjectOutputStream.defaultWriteObject(). 2) Однако, если мы создадим свои методы readObject() и writeObject(), то Serizalizable не сможет присвоить значение переменной: будет жаловаться, что она final. 3) У интерфейса Externalizable будет проблема в методе readExternal(). Он не сможет сделать this.field = in.readValue(). Потому что создает объект конструктором, а затем меняет значение.

Что нужно сделать, чтобы сериализовать объект?

1) Класс объекта должен реализовывать интерфейс Serializable 2) Создать поток *ObjectOutputStream* (oos), который записывает объект в переданный *OutputStream*. 3) Записать в поток: *oos.writeObject*(Object); 4) Сделать oos.flush() и oos.close()

Где ставится ключевое слово transient? Что оно означает?

1) Слово transient ("временный, переходный") - это модификатор для поля класса. 2) Если поле объявлено transient, это значит, что значение этого поля не нужно записывать при сериализации. 3) При восстановлении объекта у него будет это поле, но со значением null (0, false).

Зачем может понадобиться вручную определять методы сериализации (read/writeObject, read/writeExternal)?

1) Чтобы сериализовать не все поля. 2) Чтобы повысить производительность. 3) Чтобы зашифровать данные в полях.

Что такое совместимые и несовместимые изменения в механизме серилизации Java? Какие это изменения?

Compatible и incompatible changes - изменения в классе, после которых ранее сериализованные объекты еще можно как-то восстановить или нельзя. 1) Совместимые добавление, изменение, удаление поля или метода. 2) Несовместимые: изменение места класса в иерархии классов (например, extends другого родителя), удаление надписи implements Serializable.

Можно ли как-то вручную управлять процессом сериализации в Java?

Да, можно. Мы можем создать в классе методы: 1) *private void writeObject(ObjectOutputStream out) throws IOException* *private void readObject(ObjectInputStream in)t hrows IOException, ClassNotFoundException* Увидев эти методы, JVM будет вызывать их вместо стандартных. ВНИМАНИЕ: это *НЕ @Override!* Но это фича на уровне JVM. 2) Внутри этих методов можно вызвать "обычную" их реализацию, написав: out.defaulWriteObject(); in.defaultReadObject();

Как легко сгенерировать serialVersionUID для класса?

Для этого есть утилита *serialver*, имеющаяся в JDK: $ serialver -classpath . Hello Hello: static final long SerialVersionUID = -4862926644813433707L;

Вы сериализовали объект, а затем переименовали поле. Что будет при восстановлении?

Если в объекте указан serialVersionUID, то объект восстановится, но значение в поле - нет. Оно будет инициализировано null, 0 и т.д.

Что будет, если мы попробуем сериализовать класс, в котором не написано implements Serializable?

Код скомпилируется, но во время выполнения выкинет *java.io.NotSerializableException*

Что если мы наследовали Serizlizable класс, но хотим сделать его не-Serializable?

Нужно создать в классе собственные методы сериализации: writeObject() и readObject(). А в этих методах выкидывать исключение. Например: throw new NotSerializableException("Not serializable");

Мы записали в ObjectOutputStream out: out.writeObject(obj); out.writeInt(2); А затем в ObjectInputStream in вызываем: in.readInt(); in.readObject(); Что произойдет?

Поскольку записан объект, а мы пытаемся прочитать примитивный тип, то выпадет *java.io.OptionalDataException*. То же будет и если мы записали примитив, а считать хотим объект. А вот записать примитив и считать другой примитив можно.

Мы сериализовали объект класса Test и передали его на другую машину, где нет класса Test. Что будет, когда мы вызовем метод objectInputStream.readObject() ?

Поскольку класс не будет найден, будет выкинуто *java.lang.ClassNotFoundException*.


Kaugnay na mga set ng pag-aaral

Yr9 CC (LT1): Alexander the Great (3): King of Persia

View Set

Digital Annotation PDF & Vocabulary Lesson

View Set

N136 MCA-2 Week 4 Neurologic and Sensory Systems

View Set

Unit 8: Lesson 2: Feudalism and the Manor Economy Q&A

View Set