— Пам'ятаєш, ми розбирали збереження об'єктів у файл та читання з файлу?

— Так, тільки ми зберігали до потоку виведення, а читали з потоку введення.

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

— А що там писати? Оголосив 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, і все це чудово серіалізується та десеріалізується.

— Десеріалізується?

Десеріалізація – це зворотний до серіалізації процес – читання та відновлення об'єкта з потоку/файла.

— Тоді питань більше нема.