Бесплатный курс по Java: от основ до продвинутого уровня
Метод Clone в Java. Его переопределение
Второй метод Object это метод clone, который клонирует объект.
Происходит копирование всех полей клонируемого объекта в новый объект-клон.
Но по умолчанию методом clone в новый объект копируются только примитивные поля объекта, а ссылочные нет, поэтому clone тоже нужно переопределять.
В Java управление объектами осуществляется с помощью ссылочных переменных, инет операторадля фактического копирования объекта, поэтому и существует clone.
Переопределение Clone
Напрямую вызвать clone у какого либо объекта в main нельзя, так как метод clone внутри Object объявлен protected.
Поэтому для того чтобы вызвать clone у какого либо объекта еговсегда нужно переопределять.
То есть имеется ввиду, что даже чтобы использовать стандартную реализацию clone, которая копирует только примитивные поля всё равно нужно сделать минимальное переопределение clone, как это сделано в классе SomeClass ниже.
Создадим два класса, в которых будем переопределять clone.
Все классы, которые переопределяют clone должны реализовывать интерфейсCloneable. То есть видим ниже в примере программы implements Cloneable
Пример программы:
import java.util.*;
class SomeClass implements Cloneable {
int someVar;
SomeClass(int someVar){
this.someVar = someVar;
}
//неопределим clone для SomeClass
@Override
public SomeClass clone() throws CloneNotSupportedException{
//Слово super это супер класс то есть класс
// от которого наследует текущий класс
//Текущий класс наследует от Object.
//Слово super это ссылка на родительский класс Object.
//super.clone() – через супер класс клонируем
//текущий объект. Как уже было сказано
//у нового объекта copy копируются только примитивные
//поля объекта SomeClass. В нашем случае someVar.
Object obj = super.clone();
//Теперь новый объект clone SomeClass пока типа Object
//нам нужно привести его к SomeClass.
SomeClass someclass = (SomeClass)obj;
//Мы можем это сделать так как
//SomeClass наследует от Object.
//class SomeClass – extends Object;
//А значит имеет в своем составе
//все поля и методы SomeClass и в него были
//скопированы все НЕ ссылочные поля то есть someVar
//Ссылочных полей здесь нет
//поэтому такого переопределения достаточно
return someclass;//возвращаем клон
}
public String toString(){
return “SomeClass{“+ “someVar=” + someVar + ‘}’;
}
}
class MyClass implements Cloneable {
int myA;
SomeClass myB;
MyClass(int myA, SomeClass myB){
this.myA = myA;
this.myB = myB;
}
//clone должен копировать как простые
//так и ссылочные типы объекта
@Override
public MyClass clone() throws CloneNotSupportedException{
//Здесь для клонирования не ссылочных полей
//объекта MyClass производится те же действия
//что и в предыдущем классе.
Object obj = super.clone();
MyClass myclass = (MyClass)obj;
//В этом классе уже есть ссылочное поле это myB,
//его нужно клонировать. Для этого
//мы должны вызвать метод clone() из переопределения
//SomeClass. Он клонирует все примитивные поля
//из объекта myB, который является объектом
//SomeClass, который мы сейчас клонировали.
//И возвращает myclass, который является клоном.
myclass.myB = myB.clone();
return myclass;
}
public String toString(){
return “MyClass{” + “myA=” + myA + “, myB=” + myB + ‘}’;
}
}
public class CloneLesson {
public static void main(String[] args)
throws CloneNotSupportedException {
//Создаем объект SomeClass и объект MyClass
SomeClass someClass = new SomeClass(10);
MyClass myclass = new MyClass(10,someClass);
//клонируем myclass.
MyClass myclass1 = myclass.clone();
//Выведем на консоль поля клонируемого
//объекта и клона.
System.out.println(myclass);
//Как можно увидеть по результатам все поля
//примитивного типа и все типы ссылочные
//очень someClass из myclass.
System.out.println(myclass1);
//Теперь самое главное. Нужно точно убедиться
//что объекты myclass и myclass1 не ссылаются на один
//и тот же объект и тогда точно можно будет сказать
//что клонирование прошло успешно. Для этого создадим
//новый объект someClass и присвоим его полю myB
//объекта myclass1. Если клонирование прошло успешно
//то объект someClass никак не должен измениться
//в объекте myclass и убедимся что это не произошло.
//Если клонирование прошло успешно то объекты
//myclass и myclass1 будут разные, что они и отдельны.
someClass = new SomeClass(12);
myclass1.myB = someClass;
System.out.println(myclass);
System.out.println(myclass1);
//Теперь изменим ссылочное поле в myclass1
//и убедимся что это не изменило myclass
myclass1.myB.someVar = 12;
System.out.println(myclass);
System.out.println(myclass1);
}
}