java clone

来源:互联网 发布:fc2免费破解版域名 编辑:程序博客网 时间:2024/06/03 16:53

对于java里面的clone方法,我们学习的时候会觉得不像其他方法一样好理解,其实只要我们细心思考一下,就会觉得还是可以理解的。

在java中,clone()是声明在Object中的,源码是:

public class Object{

protected native Object clone() throws CloneNotSupportedException;

}

那么我们分开来理解

首先为什么这里要把clone方法写成protected的呢?

java机制为所有对象提供了clone()方法(因为所有类继承Object,也就继承了clone()方法),但是又处于安全考虑,所以将他们设置为保护属性。

当然即使这样我们仍然可以利用java反射机制在任意对象中调用它。

那么为什么又写成native呢?

对于这点我们不深究,在这里我们只要知道native方法的效率一般来说都远高于java中非native方法就好了。

对于后面的那个克隆不支持异常相信大家都理解也不多说,那么我们重点看下面几个问题。

首先我们要知道如何使用clone()方法?

clone()中有两种拷贝方式,一种是浅克隆(复制),另一种是深克隆(复制)。

通过代码说明:

浅复制:被复制的对象的所有成员属性都有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。

换言之,浅层复制仅仅复制所考虑的对象,而不复制它所引用的对象。

public class ShallowCopy implements Cloneable{

private Date begin;

public Date getBegin(){return this.begin};

public Date setBegin(Date data){this.begin = data};

public Object clone(){

Object obj = null;

try{

obj = super.clone();

}catch(CloneNotSupportedException e){

e.printStackTrace();

}

return obj;

}

}

深复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。

那些引用其他对象的变量将指向被复制过的新对象,而不是原有的那些被引用的对象。

换言之,深层复制要复制的对象引用的对象都复制一遍。

public class DeepCopy implements Cloneable{

private Date begin;

public Date getBegin(){return this.begin};

public Date setBegin(Date data){this.begin = data};

public DeepCopy clone(){

DeepCopy obj = null;

try{

obj = (DeepCopy)super.clone();

}catch(CloneNotSupportedException e){

e.printStackTrace();

}

obj.setBegin((Date)this.getBegin().clone());

return obj;

}

}

无论是从浅克隆还是深克隆我们都可以看出,要实现克隆功能,就要实现Cloneable接口,否则虽然编译可以通过,但是运行时会出现CloneNotSupportedException 

既然使用clone()方法要实现Cloneable接口,为什么不干脆把clone()方法放到Cloneable接口中呢?

其实这是没有必要的,因为我们知道,在接口中的定义的方法一旦某个类实现该接口那么我们就要重写这个方法,但是对于clone()来说,显然我们想让每个类支持

克隆功能,但是我们有没有必要刻意去重写clone()方法,所以将clone()放在Object里面。然后用implements Cloneable标记该类是否支持克隆即可。比如

public class Test implements Cloneable{

private int num = 1;

public static void main(String[] args){

Test a = new Test();

try {

Test t = (Test)a.clone();

System.out.println(t.num);

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

}

}

那么clone()方法既然在Object中,那Object为什么没有实现这个接口呢?

我们知道java中Object类是所有类的父类,这也就是为什么java中说一切皆对象,虽然我们在Object对象中有clone()方法,

但是并没有给它实现cloneable接口,因为我们需要的只是提供一个克隆方法给所有类,代表所有类都可以被克隆,所以在这里

我们并不需要实现cloneable接口。而是在各个子类中我们根据自己需求考虑是不是实现clone()功能,即是不是要实现cloneable接口。

如果在Object中实现Cloneable接口,那么Object的所有子类,也就是说所有类都可以不加控制的被拷贝,只要重写clone()方法,这显然是不合理的。


查看API可以看到克隆对象有以下特点:

假设X是一个非空对象,则

1)x.clone()!=x为true,就是说他们不是同一个对象

2)xclone().getClass() == x.getClass()为true,说明他们是同一类型

2)x.equals(x.clone())为true,说明逻辑上应该相当



0 0