Метод clone
в Object
, который создает точную копию объекта, объявляется как:
protected native Object clone() throws CloneNotSupportedException;
Почему это native
?
Метод clone
в Object
, который создает точную копию объекта, объявляется как:
protected native Object clone() throws CloneNotSupportedException;
Почему это native
?
В принципе, поскольку метод clone()
делает то, что вы не можете сделать на языке Java: он клонирует состояние объекта, включая его фактическое обозначение класса.
Механизм клонирования в Java основан на каждом классе, вызывающем метод суперкласса clone
, вплоть до Object
. Затем объект использует этот "магический" родной метод clone
для дублирования исходного объекта, включая его фактический класс.
Подумайте об этом:
class A implements Cloneable {
public A clone() {
A obj = (A) super.clone();
// Do some deep-copying of fields
return obj;
}
}
class B extends A {
public B clone() {
B obj = (B) super.clone();
// Do some deep-copying of fields not known to A
return obj;
}
}
Теперь представьте, что у вас есть объект типа B
, и вы вызываете clone
на нем. Вы ожидаете получить объект B
, класс которого внутренне распознан как B
, а не как Object
. B
не знает реализации всего в A
, и поэтому ему нужно вызвать метод A
clone
. Но если A
реализовал clone
на языке Java, а не вызывал super.clone()
, то возвращаемый им объект должен был бы быть A
. Он не может использовать new B()
(предполагается, что B не был известен, когда был создан A).
Он мог бы что-то сделать с отражением, но как бы он знал, какой конструктор должен вызвать так, чтобы все конечные поля были правильно заполнены?
Итак, трюк заключается в том, что A
не делает это сам, он вызывает super.clone()
, и это полностью возвращается к Object
, и он использует собственный метод, который побайтно копирование исходного объекта, настройка для нового местоположения кучи. Таким образом, новый объект магически становится объектом B
, и литье типов не будет терпеть неудачу.
Почему бы не вернуть Object
? Потому что это не клонирование. Когда вы вызываете clone
, вы ожидаете получить объект как с одним и тем же состоянием (поля), так и с тем же классом (переопределенные и добавленные методы). Если он возвратил объект, чье внутреннее обозначение класса было Object
, у вас был бы доступ только к тем вещам, которые Object
предлагает, например toString()
, и вы не сможете получить доступ к своим закрытым полям из другого B
объект или присвоить его переменной типа B
.
Посмотрите на документацию клонов:
В противном случае этот метод создает новый экземпляр класса этого объект и инициализирует все его поля с точно содержимым соответствующие поля этого объекта, как бы путем присвоения; содержимое поля сами не клонируются.
Эта операция может быть выполнена очень эффективно с помощью собственного кода, так как некоторая память должна быть скопирована напрямую. Аналогично в этом отношении System.arrayсopy
, который также является родным. Подробнее см. Этот вопрос: Возможно ли найти источник для родного метода Java?
Обратите внимание, что обычно вы должны избегать Object.clone() и вместо этого использовать, например, конструктор копирования, см. Как скопировать объект в Java? p >
Он является родным, потому что некоторые методы системных классов Clone()
написаны на С++ для повышения производительности.