该 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() (假设在创建A时不知道B)。
它可以用反射做一些事情,但它如何知道要调用哪个构造函数以便所有最终字段都能正确填充?
所以诀窍是 A 它本身并没有这样做 super.clone(),这一直都是回归 Object,它使用一个本机方法,对原始对象进行逐字节复制,调整新的堆位置。因此,新对象神奇地变成了一个 B 对象和类型转换不会失败。
为什么不回来 Object 然后?因为那不会是克隆。你打电话时 clone 你期望获得两个相同状态(字段)的对象,并且相同 类 (重写和添加方法)。如果它返回了一个内部类名称为的对象 Object,你只能访问那些东西 Object 提供,如 toString(),您将无法从另一个访问其私有字段 B 对象,或将其分配给 B 类型变量。
查看克隆文档:
否则,此方法将创建此类的新实例 对象并初始化其所有字段的确切内容 该对象的相应字段,好像是通过赋值;内容 这些田地本身没有克隆。
使用本机代码可以非常有效地完成此操作,因为必须直接复制某些内存。在这方面类似 System.arrayсopy,这也是原生的。有关详细信息,请参阅此问 是否有可能找到Java本机方法的源代码?
请注意,通常应该避免使用Object.clone(),而是使用复制构造函数,请参阅 如何在Java中复制对象?
它是原生的,因为有些系统类' Clone() 方法是用C ++编写的,以提高性能。