
— Привет, Амиго!
— Привет, Билаабо!
— Сегодня я расскажу тебе про интерфейсы-маркеры.
Интерфейсы-маркеры – это интерфейсы, которые не содержат методов. Когда класс наследуется от такого интерфейса, то говорят, что он им помечен.
Примеры таких интерфейсов: 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, для чтения (десериализации) объекта.
На 11-й строчке мы читаем наш объект и преобразуем его к типу BigObject.
Как тебе?
— Красота.
Кстати, когда код раскрашен разными цветами – гораздо легче его понимать.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ