logo

Метод Clone() в Java

Клонування об’єкта означає створення точної копії об’єкта. Він створює новий екземпляр класу поточного об’єкта та ініціалізує всі його поля саме вмістом відповідних полів цього об’єкта.

Методи виконання клонування об'єктів у Java

Нижче наведено 3 методи створення клонування об’єктів у Java:

  1. Використання оператора присвоєння для створення копії еталонної змінної
  2. Створення копії за допомогою методу clone().
  3. Використання методу clone() – Deep Copy

1. Використання оператора присвоєння для створення a копія еталонна змінна

У Java немає оператора для створення копії об’єкта. На відміну від C++, у Java, якщо ми використовуємо оператор присвоєння, він створить копію посилальної змінної, а не об’єкта. Це можна пояснити на прикладі. Наступна програма демонструє те саме.



Нижче наведено реалізацію вищезазначеної теми:

Java




// Java program to demonstrate that assignment operator> // only creates a new reference to same object> import> java.io.*;> > // A test class whose objects are cloned> class> Test {> >int> x, y;> >Test()> >{> >x =>10>;> >y =>20>;> >}> }> > // Driver Class> class> Main {> >public> static> void> main(String[] args)> >{> >Test ob1 =>new> Test();> > >System.out.println(ob1.x +>' '> + ob1.y);> > >// Creating a new reference variable ob2> >// pointing to same address as ob1> >Test ob2 = ob1;> > >// Any change made in ob2 will> >// be reflected in ob1> >ob2.x =>100>;> > >System.out.println(ob1.x +>' '> + ob1.y);> >System.out.println(ob2.x +>' '> + ob2.y);> >}> }>

>

>

Вихід

10 20 100 20 100 20>

2. Створення копії методом clone().

Клас, чия копія об’єкта має бути створена, повинен мати загальнодоступний метод клонування в ньому або в одному з його батьківських класів.

  • Кожен клас, який реалізує clone(), повинен викликати super.clone(), щоб отримати посилання на клонований об’єкт.
  • Клас також має реалізувати інтерфейс java.lang.Cloneable, клон об’єкта якого ми хочемо створити, інакше він викличе CloneNotSupportedException, коли метод clone викликається для об’єкта цього класу.

Синтаксис:

protected Object clone() throws CloneNotSupportedException>

i) Використання методу clone() - Shallow Copy

Примітка – У наведеному нижче прикладі коду метод clone() створює абсолютно новий об’єкт з іншим значенням hashCode, що означає, що він знаходиться в окремій області пам’яті. Але через те, що тестовий об’єкт c знаходиться всередині Test2, примітивні типи досягли глибокої копії, але цей тестовий об’єкт c все ще спільно використовується між t1 і t2. Щоб подолати це, ми явно робимо глибоку копію для об’єктної змінної c, яка обговорюється пізніше.

Java




// A Java program to demonstrate> // shallow copy using clone()> import> java.util.ArrayList;> > // An object reference of this class is> // contained by Test2> class> Test {> >int> x, y;> }> > // Contains a reference of Test and> // implements clone with shallow copy.> class> Test2>implements> Cloneable {> >int> a;> >int> b;> >Test c =>new> Test();> >public> Object clone()>throws> CloneNotSupportedException> >{> >return> super>.clone();> >}> }> > // Driver class> public> class> Main {> >public> static> void> main(String args[])> >throws> CloneNotSupportedException> >{> >Test2 t1 =>new> Test2();> >t1.a =>10>;> >t1.b =>20>;> >t1.c.x =>30>;> >t1.c.y =>40>;> > >Test2 t2 = (Test2)t1.clone();> > >// Creating a copy of object t1> >// and passing it to t2> >t2.a =>100>;> > >// Change in primitive type of t2 will> >// not be reflected in t1 field> >t2.c.x =>300>;> > >// Change in object type field will be> >// reflected in both t2 and t1(shallow copy)> >System.out.println(t1.a +>' '> + t1.b +>' '> + t1.c.x> >+>' '> + t1.c.y);> >System.out.println(t2.a +>' '> + t2.b +>' '> + t2.c.x> >+>' '> + t2.c.y);> >}> }>

>

>

Вихід

10 20 300 40 100 20 300 40>

У наведеному вище прикладі t1.clone повертає поверхневу копію об’єкта t1. Щоб отримати глибоку копію об’єкта, необхідно внести певні зміни в метод clone після отримання копії.

ii) Використання методу clone() – Deep Copy

  • Якщо ми хочемо створити глибоку копію об’єкта X і помістити її в новий об’єкт Y, тоді створюється нова копія будь-яких полів об’єктів, на які посилаються, і ці посилання розміщуються в об’єкті Y. Це означає, що будь-які зміни, зроблені в полях об’єктів, на які посилаються, в об’єкті X або Y буде відображено лише в цьому об’єкті, а не в іншому. У прикладі нижче ми створюємо глибоку копію об’єкта.
  • Глибока копія копіює всі поля та створює копії динамічно виділеної пам’яті, на яку вказують поля. Глибока копія виникає, коли об’єкт копіюється разом із об’єктами, на які він посилається.

Java




// A Java program to demonstrate> // deep copy using clone()> > // An object reference of this> // class is contained by Test2> class> Test {> >int> x, y;> }> > // Contains a reference of Test and> // implements clone with deep copy.> class> Test2>implements> Cloneable {> >int> a, b;> > >Test c =>new> Test();> > >public> Object clone()>throws> CloneNotSupportedException> >{> >// Assign the shallow copy to> >// new reference variable t> >Test2 t = (Test2)>super>.clone();> > >// Creating a deep copy for c> >t.c =>new> Test();> >t.c.x = c.x;> >t.c.y = c.y;> > >// Create a new object for the field c> >// and assign it to shallow copy obtained,> >// to make it a deep copy> >return> t;> >}> }> > public> class> Main {> >public> static> void> main(String args[])> >throws> CloneNotSupportedException> >{> >Test2 t1 =>new> Test2();> >t1.a =>10>;> >t1.b =>20>;> >t1.c.x =>30>;> >t1.c.y =>40>;> > >Test2 t3 = (Test2)t1.clone();> >t3.a =>100>;> > >// Change in primitive type of t2 will> >// not be reflected in t1 field> >t3.c.x =>300>;> > >// Change in object type field of t2 will> >// not be reflected in t1(deep copy)> >System.out.println(t1.a +>' '> + t1.b +>' '> + t1.c.x> >+>' '> + t1.c.y);> >System.out.println(t3.a +>' '> + t3.b +>' '> + t3.c.x> >+>' '> + t3.c.y);> >}> }>

>

>

словник c#
Вихід

10 20 30 40 100 20 300 40>

У наведеному вище прикладі ми бачимо, що новий об’єкт для класу Test було призначено для копіювання об’єкта, який буде повернено до методу clone. Завдяки цьому t3 отримає глибоку копію об'єкта t1. Таким чином, будь-які зміни, внесені в полях об’єкта «c» t3, не будуть відображені в t1.

Глибоке копіювання проти поверхневого копіювання

Існують певні відмінності між використанням clone() як глибокої копії та використанням як поверхневої копії, як зазначено нижче:

  • Неглибока копія це метод копіювання об'єкта, який за умовчанням дотримується під час клонування. У цьому методі поля старого об’єкта X копіюються в новий об’єкт Y. Під час копіювання поля типу об’єкта посилання копіюється в Y, тобто об’єкт Y вказуватиме на те саме місце, на яке вказує X. Якщо значення поля є примітивним типом, він копіює значення примітивного типу.
  • Таким чином, будь-які зміни, зроблені в об’єктах, на які посилаються, в об’єкті X або Y будуть відображені в інших об’єктах.

Неглибокі копії дешеві та прості у виготовленні. У наведеному вище прикладі ми створили поверхневу копію в об'єкт.

Навіщо використовувати метод clone() або Переваги методу клонування

  • Якщо ми використовуємо оператор присвоєння, щоб призначити посилання на об’єкт іншій змінній посилання, тоді воно вказуватиме на те саме розташування адреси старого об’єкта, і нова копія об’єкта не буде створена. Завдяки цьому будь-які зміни в еталонній змінній будуть відображені в оригінальному об'єкті.
  • Якщо ми використовуємо конструктор копіювання, то нам потрібно явно скопіювати всі дані, тобто нам потрібно явно перепризначити всі поля класу в конструкторі. Але в методі клонування ця робота зі створення нової копії виконується самим методом. Тому, щоб уникнути додаткової обробки, ми використовуємо клонування об’єктів.