Метод clone, интерфейс Cloneable - 1

— Привет, Амиго!

— Привет, Ким.

— Я тебе расскажу про метод clone().

Цель этого метода – клонировать объект – т.е. создать его клон/копию/дубликат.

Если его вызвать, то Java-машина создаст и вернет дубликат объекта, у которого вызвали этот метод.

Клонирование объекта в классе Object реализовано очень примитивно – при клонировании создается всего один новый объект: просто создается еще один объект и его полям присваиваются значения полей объекта-образца.

Если копируемый объект содержит ссылки на другие объекты, то ссылки будут скопированы, дубликаты тех объектов не создаются.

— Гм. Не густо.

— Дело в том, что Java-машина не знает, какие объекты можно клонировать, а какие нет. Файлы, например, клонировать нельзя. Как и поток System.in.

Поэтому вопрос о полноценном клонировании был отдан на откуп разработчикам классов. Тут все было сделано по аналогии с методом equals. Даже есть свой аналог hashCode – это интерфейс Cloneable.

Интерфейс Cloneable – это так называемый интерфейс-маркер, который не содержит никаких методов. Он используется, чтобы маркировать (помечать) некоторые классы.

Если разработчик класса считает, что объекты класса можно клонировать, он помечает класс этим интерфейсом (наследует класс от Cloneable).

Если разработчика не устраивает стандартная реализация метода clone, он должен написать свою, которая будет создавать дубликат объекта правильным образом.

При вызове метода clone(), Java проверяет, был ли у объекта интерфейс Cloneable. Если да — клонирует объект методом clone(), если нет — выкидывает исключение CloneNotSupportedException.

— Т.е. мы должны или переопределить метод clone и написать его новую реализацию или унаследовать класс от Cloneable?

— Да, но переопределять метод все же придется. Метод clone() объявлен как protected, так что он доступен для вызова только классам из его пакета (java.lang.*) или классам-наследникам.

— Я немного запутался, так что же надо сделать, чтобы клонировать объект?

— Смотри, если ты хочешь воспользоваться «клонированием по умолчанию», которое реализовано в классе Object, тебе нужно:

а) Добавить интерфейс Cloneable своему классу

б) Переопределить метод clone и вызвать в нем базовую реализацию:

class Point implements Cloneable
{
 int x;
 int y;

 public Object clone()
 {
  return super.clone();
 }
}

Или ты можешь написать реализацию метода clone полностью сам:

class Point 
{
 int x;
 int y;

 public Object clone()
 {
  Point point = new Point();
  point.x = this.x;
  point.y = this.y;
  return point;
 }
}

— Интересный метод, буду пользоваться. Иногда…