Контроль сериализации
Что обозначает ключевое слово transient?
transient исключает поле экземпляра из стандартной сериализованной формы. При обычной десериализации такое поле получает значение по умолчанию, если пользовательский readObject не восстанавливает его отдельно. Пример ниже демонстрирует явную запись transient-поля; это не защита данных.
Пример:import java.io.*;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String note; // не будет сериализовано стандартным способом
public Person(String name, int age, String note) {
this.name = name;
this.age = age;
this.note = note;
}
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject(); // стандартная сериализация
oos.writeObject(encodeDemo(note)); // дополнительная логика (учебное преобразование строки)
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject(); // стандартная десериализация
note = decodeDemo((String) ois.readObject()); // дополнительная логика (обратное учебное преобразование строки)
}
private String encodeDemo(String data) {
return new StringBuilder(data).reverse().toString(); // обратимое преобразование, не шифрование
}
private String decodeDemo(String data) {
return new StringBuilder(data).reverse().toString(); // обратное преобразование
}
}
Как не допустить сериализацию?
Чтобы не допустить сериализацию класса в Java, можно использовать несколько подходов:
-
Не реализовывать интерфейс
Serializable: Самый простой способ — не реализовывать интерфейсSerializableв классе. Если класс не реализует этот интерфейс, попытки сериализовать его объекты приведут к выбросу исключенияNotSerializableException. -
Использовать
transientдля полей: Помечать поля какtransient, если они не должны быть сериализованы. Это подход применим для отдельных полей, а не для всего класса. -
Имплементировать
writeObjectиreadObjectметоды с исключением: Можно определить методыwriteObjectиreadObjectв классе, которые будут выбрасывать исключение, предотвращая таким образом сериализацию.
import java.io.*;
public class NonSerializableClass implements Serializable {
private static final long serialVersionUID = 1L;
private String data;
public NonSerializableClass(String data) {
this.data = data;
}
private void writeObject(ObjectOutputStream oos) throws IOException {
throw new NotSerializableException("Serialization is not allowed for this class");
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
throw new NotSerializableException("Deserialization is not allowed for this class");
}
// геттеры и сеттеры
}
В этом примере попытки сериализовать или десериализовать объекты класса NonSerializableClass будут выбрасывать исключение NotSerializableException.