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

Открыта

— Помнишь, мы сегодня разбирали сохранение объектов в файл и чтение из файла?

— Да, только мы сохраняли в поток вывода, а читали из потока ввода.

— Молодец, Амиго. Приятно слышать, что ты замечаешь такие мелочи. А ты бы смог дописать код, чтобы было сохранение в файл и чтение из файла?

— А что там писать?! Объявил FileInputStream и FileOutputStream и передавай их в методы save & load. Тут уже ничего не перепутаешь — все просто.

— Рада за тебя. Итак, новая тема – сериализация.

Сериализация – это практически то же самое, что мы с тобой только что делали, только гораздо круче и встроено прямо в Java-машину. Java-машина умеет сохранять и загружать свои объекты. Для этого ей даже не требуются методы save & load: все объекты хранятся внутри Java-машины, и она имеет к ним полный доступ.

Мы просто берем объект и сохраняем его в поток/читаем из потока:

Код
public static void main(String[] args) throws Exception
{
 Cat cat = new Cat();

 //save cat to file
 FileOutputStream fileOutput = new FileOutputStream("cat.dat");
 ObjectOutputStream outputStream = new ObjectOutputStream(fileOutput);
 outputStream.writeObject(cat);
 fileOutput.close();
 outputStream.close();

 //load cat from file
 FileInputStream fiStream = new FileInputStream("cat.dat");
 ObjectInputStream objectStream = new ObjectInputStream(fiStream);
 Object object = objectStream.readObject();
 fiStream.close();
 objectStream.close();

 Cat newCat = (Cat)object;
}

— И все?

— Да. Там очень большой и сложный механизм сериализации, который поддерживает сохранение в поток и чтение из потока почти всех типов данных.

— Почти всех, это значит не всех?

— Да, дело в том, что не все объекты по своей сути можно сохранить. Некоторые объекты не хранят все свои данные в себе, а лишь ссылаются на другие объекты и/или источники данных. Например, консоль (System.in), поток ввода (InputStream), или что-нибудь еще.

Поэтому разработчики Java придумали специальный интерфейс-маркер – Serializable. Его называют маркером, т.к. он не содержит никаких данных и методов. Он используется только для того, чтобы «помечать» (маркировать) классы. Если мы считаем, что наш класс хранит в себе все свои данные, тогда мы можем пометить его этим маркером – написать implements Serializable.

Пример «кота» с поддержкой сериализации:

Код
class Cat implements Serializable
{
 public String name;
 public int age;
 public int weight;
}

Когда мы пытаемся сериализовать (сохранить) какой-нибудь объект, Java-машина проверяет – поддерживает ли он сериализацию: реализует ли он интерфейс Serializable? Если да, то сохраняет объект, если нет – выкидывает исключение о невозможности сериализации.
Тут нужно понимать, что сериализуемый объект должен состоять тоже только из сериализуемых объектов.

— Ну, этого и следовало ожидать. Нельзя же сохранить целое, не сохранив какие-то его части.

— Именно так.

— А как же типы int, String, ArrayList?

— Они все поддерживают сериализацию, на этот счет разработчики Java специально позаботились. Тут проблем быть не должно.

Более того, при сериализации объекта сохраняется его тип. Теперь ты можешь в переменную класса с типом Object сохранить ссылку на объект Cat, и все это отлично сериализуется и десериализуется.

— Десериализуется?

— Десериализация – так называют процесс, обратный сериализации – чтение и восстановление объекта из потока/файла.

— Тогда вопросов больше нет.

Комментарии (5)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Dmytrii
Уровень 70
29 марта, 17:23
а где все? как-то страшно становится, в комментариях людей соро совсем не будет 😬
Олег
Уровень 111
Expert
21 мая 2023, 20:12
В Java не все объекты могут быть сериализованы. Вот некоторые типы объектов, которые не поддерживают сериализацию: Статические поля: Статические поля не сохраняются при сериализации, так как они принадлежат классу, а не объекту. Переходные (transient) поля: Поля, помеченные ключевым словом transient, не участвуют в процессе сериализации. Они считаются временными или незначимыми и не должны быть сохранены. Статические или локальные переменные: Статические и локальные переменные не могут быть сериализованы, так как они не являются частью состояния объекта. Анонимные классы: Анонимные классы, которые не имеют имени и определены внутри метода, не могут быть сериализованы. Некоторые встроенные классы: Некоторые встроенные классы, такие как потоки (Thread) или сокеты (Socket), не могут быть сериализованы из-за своей природы, связанной с системными ресурсами. Классы, не реализующие интерфейс Serializable: Объекты классов, которые не реализуют интерфейс Serializable, не могут быть сериализованы. В целом, чтобы объект мог быть сериализован, его класс должен реализовывать интерфейс Serializable и все поля, которые нужно сериализовать, должны быть сериализуемыми.
Олег
Уровень 111
Expert
21 мая 2023, 20:12
Сериализация в Java - это процесс преобразования объекта в последовательность байтов, которая может быть сохранена в файле или передана по сети, и далее восстановления этого объекта из последовательности байтов. Сериализация позволяет сохранять состояние объектов и передавать их между различными компьютерами или программами. Для сериализации объект должен реализовывать интерфейс Serializable.
Владимир
Уровень 109
Expert
30 июня 2022, 15:50
эта статья окажется полезной, если последняя задача вызвала недоумение)))
СергейРаботает в ITQ-GroupExpert
4 августа 2022, 16:33
Я бы добавил эти две статьи для лучшего понимания https://habr.com/ru/post/60317/ https://habr.com/ru/post/431524/