您的位置:首页 > 编程语言 > Java开发

Java对象克隆问题

2015-10-12 14:21 246 查看

Object中 clone方法的源代码

/**
创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。这样做的目的是,对于任何对象 x,表达式:
x.clone() != x
为 true,表达式:
x.clone().getClass() == x.getClass()
也为 true,但这些并非必须要满足的要求。一般情况下:
x.clone().equals(x)
为 true,但这并非必须要满足的要求。
按照惯例,返回的对象应该通过调用 super.clone 获得。如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。
按照惯例,此方法返回的对象应该独立于该对象(正被复制的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被复制对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。
Object 类的 clone 方法执行特定的复制操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。注意,所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我复制。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。
Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。
返回:
此实例的一个副本。
抛出:
CloneNotSupportedException - 如果对象的类不支持 Cloneable 接口,则重写 clone 方法的子类也会抛出此异常,以指示无法复制某个实例。
*/
protected native Object clone() throws CloneNotSupportedException;


说明

我们知道,Java中出来常规的字符串、数组等对象所有的都是通过new创建的。

ObjectTest obj;
// 只是声明了一个变量(更像C++中的指针),该变量没有指向对象空间。

ObjectA a = new ObjectA();
ObjectA b = a;    // a b指向同一个对象空间
b = a.clone();    // b指向一个新的对象空间,该对象是由a指向(引用)的空间克隆而来。


实现深拷贝方法

/**
* @see Cloneable 接口是一个空接口, 在需要覆盖 Object中 clone()方法时候做一个“标记(表示该类要使用clone()方法)”。
* 因为Java设计人员对clone()方法的使用意见不一。
* 在默认的“机制中”,直接在类设计中调用super.clone()方法(可能与本地方法和虚拟机有关)会生成当前类的一个拷贝对象(浅拷贝模式),
* “当前类实例域”中的任用变量成员以浅拷贝的方式指向同一块空间,我们必须重新分配。
* @author yang
*
*/
public class Test implements Cloneable{
Object object;

@Override
public Object clone() throws CloneNotSupportedException {
Test t = (Test) super.clone();    // 生成一个当前对象的浅拷贝对象
t.object = new Object();
return t;
}
}


Java中没有所谓的C++中的赋值拷贝构造函数

CTest test(3);
CTest assignCopy(test); // C++中默认情况下面是浅拷贝(实例域对象指针地址值一样)
CTest(const CTest &test) // 要想深拷贝,必须覆盖拷贝构造函数。

//WString::WString(const WString &s)
//{
//    size=s.size;
//    str=new char[size+1];
//    if(str==null)
//        error("WString:overflow");
//    strcpy(str,s.str);
//}


**Java中可以通过在覆盖克隆函数时候,调用super.clone()方法生成当前类的浅拷贝对象,然后再对对象中的引用型实例域进行分配新对象空间, 但是C++不可以,

因为无法在写拷贝构造函数时调用本身。**
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java