— Давай поговоримо про метод 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;
 }
}

— Цікавий метод, користуватимуся. Іноді…