java中克隆,浅拷贝,神拷贝

来源:互联网 发布:c语言打印标准杨辉三角 编辑:程序博客网 时间:2024/05/25 21:34

      java中的引用,课本中总是告诉我们jiava中没有指针,其实不然。我们都知道在C++中指针总是带着* 出现的,在java中,指针不再叫指针,叫引用了, 而且指针声明的时候也不再有*了。java中每一个变量的名字就相当与一个引用,指向用new 申请的空间。


    提到java中的克隆,不得不先提一下设计模式中的原型模式。我们举个这样例子,加入你手头上有一份非常好的讲义,这时候,你的朋友也想要一份。难道你要手抄一份吗?当然不是,显然复印的方法来的最直接,简便,而且准去率高。这种用原型来复制而不是重新复制的思维方式就是原型模式的核心思想。我们看一下原型模式的UML图。




java中的克隆就是实现原型模式的一种重要方式,但克隆不等于原型模式。在java中,克隆主要是通过clone()这个实现的,每一个类都会从java.lang.object中继承一个clone()函数。那么这个函数是如何实现的呢。从JDK API 中我们可以了解到clone()方法将调用对象进行复制并返回了一份。并且满足以下条件;

a)对任意一个对象满足x.clone()!=x,也就是x.clone()得到的对象和x引用的内存空间不同

b)x.clone().getClass()=x.getClass(),x.clone()的到的对象和x两个对象是一个类,即二者类型一致

c)大部分情况下还满足,x.clone().equal(x)。这个地方我不太了解。

那么clone()函数是怎么实现呢,先看代码如下

public class Point implements Cloneable {public int a_pos;public int b_pos;Point(){a_pos=10;b_pos=15;}public Object clone(){Object o=null;try {o=(Point)super.clone();} catch (CloneNotSupportedException e) {// TODO Auto-generated catch blocke.printStackTrace();}return o;}}
public class MainTest {public static void main(String args[]){Point a=new Point();System.out.println(a.a_pos+" "+a.b_pos);Point b=(Point) a.clone();System.out.println(b.a_pos+" "+b.b_pos);System.out.println("a.equals(b) is "+ a.equals(b));System.out.println("a!=b is "+ (a!=b));System.out.println("a.getClass()==b.getClass() is "+ (a.getClass()==b.getClass()));}}
打印出来显示
10 15
10 15
a.equals(b) is false
a!=b is true
a.getClass()==b.getClass() is true
说明了对象a和b指向了不同的内存,也就是说对象在克隆的时候,是将对象a引用的内存进行了内存的复制,然后放到了新的内存中。那么什么叫浅拷贝呢,其实如果所有的类通过实现cloneable接口并重写clone()是可以有效避免浅拷贝的(个人观点,也许有误,请指正)
import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;public class Point implements Serializable {public int a_pos;public int b_pos;Point(){a_pos=10;b_pos=15;}public Object deepClone() throws Throwable{ByteArrayOutputStream bo=new ByteArrayOutputStream();ObjectOutputStream oo=new ObjectOutputStream(bo);oo.writeObject(this);                       //write the object into the streamByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());ObjectInputStream oi=new ObjectInputStream(bi);return(oi.readObject());}}
如有不对之处,请指正不胜感激

原创粉丝点击