Карта / I/O и файлы / Сериализация

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

Сериализация — преобразование объекта в поток байт для сохранения в файл, передачи по сети или кэширования. Десериализация — обратно: байты → объект.

В Java встроенная сериализация реализуется через интерфейс-маркер Serializable:

public class User implements Serializable {
    private String name;
    private int age;
    // serialVersionUID — версия класса для совместимости
    private static final long serialVersionUID = 1L;
}

// Сохранить объект в файл
try (ObjectOutputStream out = new ObjectOutputStream(
        new FileOutputStream("user.ser"))) {
    out.writeObject(new User("Артур", 28));
}

// Прочитать обратно
try (ObjectInputStream in = new ObjectInputStream(
        new FileInputStream("user.ser"))) {
    User user = (User) in.readObject();
}

transient — поле не сериализуется (пароли, кэши, соединения):

private transient String password;  // не попадёт в байты
Копнуть глубже

Встроенная сериализация почти не используется в современном коде. Причины:

  • Безопасность: десериализация произвольных байт — источник уязвимостей (CVE). Известные атаки через ObjectInputStream в Apache Commons, Spring.
  • Хрупкость: добавили/удалили поле → сломали совместимость.
  • Производительность: медленнее JSON/Protobuf.

На практике используют: JSON (Jackson, Gson), XML, Protobuf, Avro (для Kafka). Jackson — де-факто стандарт в Spring-приложениях:

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);   // объект → JSON
User user2  = mapper.readValue(json, User.class); // JSON → объект

serialVersionUID — важно задавать явно. Если не задан, JVM вычисляет его автоматически из структуры класса. Изменили класс (добавили поле) → serialVersionUID изменился → десериализация старых данных бросает InvalidClassException. Явный serialVersionUID = 1L даёт контроль над совместимостью.

Кастомная сериализация — переопределить writeObject/readObject для полного контроля:

private void writeObject(ObjectOutputStream out) throws IOException {
    out.defaultWriteObject();
    out.writeObject(encryptPassword(password)); // зашифровать перед записью
}
🎤 Закрыл тему, если можешь объяснить:
• что такое сериализация и как Serializable работает в Java;
• почему встроенная сериализация редко используется на практике и что вместо неё (если дошёл до 2-го слоя).