Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Object.clone() native in Java?

The clone method on Object, which creates an exact copy of an object, is declared as:

protected native Object clone() throws CloneNotSupportedException;

Why is it native?

like image 789
Aamir Avatar asked Dec 01 '14 08:12

Aamir


1 Answers

Basically, because the clone() method does something that you cannot do in the Java language: it clones the state the of the object, including its actual class designation.

The cloning mechanism in Java is based on each class calling the superclass's clone method, all the way up to Object. Object then uses this "magical" native clone method to duplicate the original object, including its actual class.

Think of this:

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;

    }
}

Now imagine that you have a B type object, and you call clone on it. You expect to get a B object, whose class is internally recognized as B, not as Object. B doesn't know the implementation of everything in A, and therefore it needs to call A's clone method. But if A implemented clone in the Java language rather than calling super.clone(), then the object it would return would have to be A. It cannot use new B() (assume B was not known when A was created).

It could do something with reflection, but how would it know which constructor to call so that all the final fields would be properly filled up?

So the trick is that A doesn't do it itself, it calls super.clone(), and this goes all the way back to Object, and it uses a native method that does a byte-by-byte copying of the original object, adjusting for the new heap location. Thus, the new object magically becomes a B object and the type casting would not fail.

Why not return an Object then? Because that would not be cloning. When you call clone you expect to get an object of both the same state (fields), and the same class (overridden and added methods). If it returned an object whose internal class designation was Object, you'd only have access to things that Object offers, such as toString(), and you would not be able to access its private fields from another B object, or to assign it to a B type variable.

like image 110
RealSkeptic Avatar answered Oct 04 '22 17:10

RealSkeptic