Почему Object.clone() является родным на Java?

Метод clone в Object, который создает точную копию объекта, объявляется как:

protected native Object clone() throws CloneNotSupportedException;

Почему это native?

Ответ 1

В принципе, поскольку метод 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.

Ответ 2

Посмотрите на документацию клонов:

В противном случае этот метод создает новый экземпляр класса этого объект и инициализирует все его поля с точно содержимым соответствующие поля этого объекта, как бы путем присвоения; содержимое поля сами не клонируются.

Эта операция может быть выполнена очень эффективно с помощью собственного кода, так как некоторая память должна быть скопирована напрямую. Аналогично в этом отношении System.arrayсopy, который также является родным. Подробнее см. Этот вопрос: Возможно ли найти источник для родного метода Java?

Обратите внимание, что обычно вы должны избегать Object.clone() и вместо этого использовать, например, конструктор копирования, см. Как скопировать объект в Java? p >

Ответ 3

Он является родным, потому что некоторые методы системных классов Clone() написаны на С++ для повышения производительности.