Reputation: 2422
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
?
Upvotes: 17
Views: 4378
Reputation: 602
clone() is native because the operation depends on the underlying platform, aka OS. Here are some facts to help grasp what is actually happening: 1. The JVM is implemented in C++ 2. C++ requires you to compile the code on the target platform/OS 3. The clone() operation takes place in memory 4. That part of the memory is controlled by the JVM (a C++ program) 5. A class is compiled to bytecode = text(ignore all the lengthy details below, they are just for illustration) So, this:
public static void main(String[] args) {
int a = 1;
int b = 2;
int c = calc(a, b);
}
static int calc(int a, int b) {
return (int) Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
}
becomes this:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: invokestatic #2 // Method calc:(II)I
9: istore_3
10: return
static int calc(int, int);
descriptor: (II)I
flags: (0x0008) ACC_STATIC
Code:
stack=6, locals=2, args_size=2
0: iload_0
1: i2d
2: ldc2_w #3 // double 2.0d
5: invokestatic #5 // Method java/lang/Math.pow:(DD)D
8: iload_1
9: i2d
10: ldc2_w #3 // double 2.0d
13: invokestatic #5 // Method java/lang/Math.pow:(DD)D
16: dadd
17: invokestatic #6 // Method java/lang/Math.sqrt:(D)D
20: d2i
21: ireturn
I know this was lengthy, but it illustrates quite clearly why clone() is faster than "new" - just grabs the state of the object as binary string and copies it without any "thought"/checks.
To learn more about bytecode, take a look at this article in DZone. And remember .... EVERYTHING in Computer Science is FAKE, including classes objects because they are just another abstraction that puts together related structs and functions, except probably for the hardware :), which most people think actually belongs in Computer Engineering, and not in CS.
Upvotes: 1
Reputation: 34648
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.
Upvotes: 13
Reputation: 17809
Look at the clone documentation:
Otherwise, this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned.
This operation can be done very efficiently with native code, as some memory has to be copied directly. It is similar in that regard to System.arrayсopy
, which is also native. For details see this question: Is it possible to find the source for a Java native method?
Note that usually you should avoid Object.clone(), and use for example a copy constructor instead, see How do I copy an object in Java?
Upvotes: 6
Reputation: 9429
It is native, because some system classes' Clone()
method are written in C++ to improve performance.
Upvotes: 0