Назад к вопросамИспользование
Использование
Middle+
69
questionbank
Как изменить стандартное поведение сериализации и десериализации в Java?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Для изменения стандартного поведения сериализации и десериализации используются методы writeObject и readObject, а также механизм Externalizable.
Использование writeObject и readObject
Класс, реализующий интерфейс Serializable, может объявлять эти методы. JVM вызовет их во время сериализации и десериализации соответственно.
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class MyCustomSerializable implements Serializable {
private String data;
private transient int sensitiveData; // это поле не будет сериализовано по умолчанию
public MyCustomSerializable(String data, int sensitiveData) {
this.data = data;
this.sensitiveData = sensitiveData;
}
// Метод вызывается во время сериализации
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject(); // Сериализует не-transient поля по умолчанию
out.writeInt(sensitiveData * 2); // Сериализуем модифицированное чувствительное поле
}
// Метод вызывается во время десериализации
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject(); // Десериализует не-transient поля по умолчанию
this.sensitiveData = in.readInt() / 2; // Десериализуем и восстанавливаем чувствительное поле
}
public String getData() {
return data;
}
public int getSensitiveData() {
return sensitiveData;
}
}
Использование Externalizable
Интерфейс Externalizable предоставляет полный контроль над процессом сериализации и десериализации. Класс должен реализовать методы writeExternal и readExternal.
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class MyExternalizable implements Externalizable {
private String publicData;
private int privateData; // Все поля будут сериализованы/десериализованы вручную
// Необходим конструктор без аргументов для Externalizable
public MyExternalizable() {
// Пустой конструктор
}
public MyExternalizable(String publicData, int privateData) {
this.publicData = publicData;
this.privateData = privateData;
}
// Метод вызывается во время сериализации
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(publicData); // Ручная сериализация publicData
out.writeInt(privateData); // Ручная сериализация privateData
}
// Метод вызывается во время десериализации
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.publicData = in.readUTF(); // Ручная десериализация publicData
this.privateData = in.readInt(); // Ручная десериализация privateData
}
public String getPublicData() {
return publicData;
}
public int getPrivateData() {
return privateData;
}
}
Сравнение подходов
| Особенность | Serializable + readObject/writeObject | Externalizable |
|---|---|---|
| Контроль | Частичный (дополнение к стандартному) | Полный |
| Сложность реализации | Проще для простых случаев | Требует больше кода для всех полей |
| Производительность | Обычно ниже | Может быть выше за счет оптимизации |
| Совместимость версий | Лучше поддерживается JVM | Требует ручного управления изменениями полей |
| transient поля | Игнорируются по умолчанию | Должны быть сериализованы/десериализованы вручную |
| Конструктор | Не требуется конструктор без аргументов (хотя по хорошей практике рекомендуется) | Требует конструктор без аргументов |