Ответ 1
Deserialization реализуется JVM на уровне ниже базовых языковых конструкций. В частности, он не вызывает никакого конструктора.
У меня есть класс, определяющий неизменяемый тип значения, который мне теперь нужно сериализовать. Неизбежность исходит из конечных полей, которые заданы в конструкторе. Я пробовал сериализацию, и он работает (на удивление?), Но я понятия не имею, как это сделать.
Здесь пример класса
public class MyValueType implements Serializable
{
private final int value;
private transient int derivedValue;
public MyValueType(int value)
{
this.value = value;
this.derivedValue = derivedValue(value);
}
// getters etc...
}
Учитывая, что класс не имеет конструктора arg, как он может быть создан и задано конечное поле?
(В стороне - я заметил этот класс, особенно потому, что IDEA не генерировал предупреждение об отсутствии "serialVersionUID" для этого класса, но успешно создало предупреждения для других классов, которые я только что сделал сериализуемыми.)
Deserialization реализуется JVM на уровне ниже базовых языковых конструкций. В частности, он не вызывает никакого конструктора.
Учитывая, что класс не имеет конструктора arg, как он может быть создан и задано конечное поле?
Происходит какая-то неприятная черная магия. В JVM есть бэкдор, который позволяет создавать объект без вызова какого-либо конструктора. Поля нового объекта сначала инициализируются значениями по умолчанию (false, 0, null и т.д.), А затем код десериализации объекта заполняет поля значениями из потока объектов.
(Теперь, когда Java открыта, вы можете прочитать код, который делает это... и плакать!)
И Майкл, и Стивен дали отличный ответ, я просто хочу предупредить вас о transient
.
Если значение по умолчанию (null
для ссылок, 0 для примитивов) неприемлемо для них после десериализации, вы должны предоставить свою версию readObject
и инициализировать его там.
private void readObject (
final ObjectInputStream s
) throws
ClassNotFoundException,
IOException
{
s.defaultReadObject( );
// derivedValue is still 0
this.derivedValue = derivedValue( value );
}