— Привіт, Аміго!
— Привіт, Білаабо!
— Сьогодні я розповім тобі про інтерфейси-маркери.
Інтерфейси-маркери – це інтерфейси, які не містять методів. Коли клас успадковується від такого інтерфейсу, то кажуть, що він помічений.
Приклади таких інтерфейсів: Cloneable, Serializable, Remote.
Інтерфейс Serializable використовується для позначення класів, які підтримують серіалізацію — як доказ того, що об'єкти класу можна автоматично серіалізувати та десеріалізувати.
Інтерфейс Remote використовується для позначення об'єктів, які підтримують віддалений виклик – виклик з іншої Java-машини та/або іншого комп'ютера.
Інтерфейс Cloneable використовується для позначення класів, які підтримують клонування.
До речі, про клонування.
Клонування поділяється на два типи – звичайне клонування та глибоке клонування.
Звичайне клонування – це коли створюється дублікат лише зазначеного об'єкта, без його внутрішніх об'єктів.
Глибоке клонування – це коли створюється дублікат об'єкта, об'єктів, на які він посилається, об'єктів, на які посилаються вони тощо.
Є дуже хороший спосіб виконати якісне глибоке клонування.
Цей спосіб підходить, навіть якщо розробники класів забули помітити його інтерфейсом Cloneable. Достатньо, щоб об'єкти були серіалізованими.
Ось що можна зробити:
1) Створити буфер (масив байт) у пам'яті.
2) Серіалізувати в нього потрібний об'єкт із подоб'єктами.
3) Десеріалізувати з буфера копію збереженої групи об'єктів.
BigObject objectOriginal = new BigObject();
ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(writeBuffer) ;
outputStream.writeObject(objectOriginal);
outputStream.close();
byte[] buffer = writeBuffer.toByteArray();
ByteArrayInputStream readBuffer = new ByteArrayInputStream(buffer) ;
ObjectInputStream inputStream = new ObjectInputStream(readBuffer) ;
BigObject objectCopy = (BigObject)inputStream.readObject();
На першому рядку ми створюємо об'єкт objectOriginal, який клонуватимемо. Він та всі його подоб'єкти повинні підтримувати серіалізацію.
На третьому рядку ми створюємо ByteArrayOutputStream – масив байт, який динамічно розтягуватиметься при додаванні до нього нових даних (як ArrayList).
На 4-му рядку ми створюємо ObjectOutputStream, який використовується для серіалізації.
У п'ятому рядку ми серіалізуємо об'єкт objectOriginal у масив байт за допомогою outputStream і зберігаємо його в масив writeBuffer.
На 8-му рядку ми перетворюємо writeBuffer у звичайний масив байт. Далі ми з цього масиву читатимемо наш новий об'єкт.
На 9-му рядку ми обертаємо buffer до класу ByteArrayInputStream, щоб із нього можна було читати, як із InputStream.
На 10-му рядку передаємо об'єкт readBuffer класу ObjectInputStream, для читання (десеріалізації) об'єкта.
/p>
На 11-му рядку ми читаємо наш об'єкт і перетворимо його до типу BigObject.
Як тобі?
— Краса.
До речі, коли код розфарбований різними кольорами – набагато легше його розуміти.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ