Что такое сериализация и как она реализована в Java?
“Сериализация это процесс сохранения состояния объекта в последовательность байт;
Реализована через интерфейс - маркер Serializable. “
Опишите процесс сериализации/десериализации с использованием Serializable.
“1) Класс объекта должен реализовывать интерфейс Serializable
2) Создать поток ObjectOutputStream (oos), который записывает объект в переданный OutputStream.
3) Записать в поток: oos.writeObject(Object):
- запись в поток метаданных о классе, ассоциированном с объектом (имя класса, идентификатор SerialVersionUID, идентификаторы полей класса);
- рекурсивную запись в поток описания суперклассов до класса java.lang.Object (не включительно);
- запись примитивных значений полей сериализуемого экземпляра, начиная с полей самого верхнего суперкласса;
- рекурсивную запись объектов, которые являются полями сериализуемого объекта.
4) Сделать oos.flush() и oos.close()”
Для выполнения десериализации под объект выделяется память, после чего его поля заполняются значениями из потока. Конструктор объекта при этом не вызывается. Однако при десериализации будет вызван конструктор без параметров родительского несериализуемого класса, а его отсутствие повлечёт ошибку десериализации.
Как изменить стандартное поведение сериализации/десериализации?
1) Использовать интерфейс Externalizable:
Переопределить методы
` writeExternal(ObjectOutput out) throws IOException
readExternal(ObjectInput in) throws IOException, ClassNotFoundException`
2) переопределить методы:
- writeObject(ObjectOutputStream )
- readObject()
- writeReplace()
- readResolve()
Как не сериализовать поле?
1) Добавить к полю модификатор transient. В таком случае после восстановления его значение будет null.
2) Сделать поле static. Значения статических полей автоматически не сохраняются.
Будет ли сериализовано final поле?
Поля с модификатором final сериализуются как и обычные. За одним исключением – их невозможно десериализовать при использовании Externalizable, поскольку final-поля должны быть инициализированы в конструкторе, а после этого в readExternal изменить значение этого поля будет невозможно. Соответственно, если необходимо сериализовать объект с final-полем неоходимо использовать только стандартную сериализацию.
Какая роль поля serialVersionUID в сериализации? как оно вычисляется? Что будет, если мы не укажем его явно?
Когда стоит изменять значение поля serialVersionUID?
serialVersionUID нужно изменять при внесении в класс несовместимых изменений, например при удалении какого-либо его атрибута.
Какие существуют способы контроля за значениями десериализованного объекта?
можно использовать интерфейс ObjectInputValidation с переопределением метода validateObject(), вызвав его после десериализации:
@Override
public void validateObject()
throws InvalidObjectException {
if ((age < 39) || (age > 60))
throw new InvalidObjectException("Invalid age");
}В чем проблема сериализации Singleton и как ее решить?
Как не допустить сериализацию?
можно переопределить private методы для создания исключительной ситуации NotSerializableException.
private void writeObject(ObjectOutputStream out) throws IOException {
throw new NotSerializableException();
}
private void readObject(ObjectInputStream in) throws IOException {
throw new NotSerializableException();
}3 способа клонирования объектов.
Почему метод clone() объявлен в классе Object, а не в интерфейсе Cloneable?
Метод clone() объявлен в классе Object с сигнатурой native, чтобы обеспечить доступ к стандартному механизму “поверхностного копирования” объектов (копируются значения всех полей, включая ссылки на сторонние объекты); он объявлен, как protected, чтобы нельзя было вызвать этот метод у не переопределивших его объектов.