黑马程序员技术交流社区

标题: java中的克隆是怎么回事 [打印本页]

作者: 张文兵    时间: 2012-6-12 23:08
标题: java中的克隆是怎么回事
对Java克隆不懂,它是怎么回事。
作者: sbeeqnui1987    时间: 2012-6-12 23:21
   java中深克隆与浅克隆
大家知道,对象是互相引用的,即对象中可能包含了另一个对象的引用,举例如:有一个Order对象,Order对象中又包含了LineItems对象,然后LineItems对象又包含了Item对象。


现在我有一个Order对象order1,它包含了一个LineItems对象items,这表示的是有一个订单order1,订单的内容是items。

现在有另一个客户想要一份订单,内容跟order1完全一样,那么在系统的逻辑层我们怎么做呢?很简单,order2=order1.clone(). 我们知道clone方法是在内存中生成一个新的对象,而不是只得到原对象的引用。这时候,有人说话了:“哦,明白了我们对order2的成员变量进行修改,是不会影响order1的。” 很可惜,这句话只对了一半。


假设order类有一个成员变量name,当然改变order2.name不会影响order1.name,因为他们在不同的内存区域。但是如果改变 order1.items呢?很遗憾,简单地使用order1.clone,是会影响到order2.items的。原因很简单,就是因为clone方法默认的是浅克隆,即不会克隆对象引用的对象,而只是简单地复制这个引用。所以在上例中,items对象在内存中只有一个,order1和order2都指向它,任何一个对象对它的修改都会影响另一个对象。

那相对浅克隆,深克隆自然就是会克隆对象引用的对象了。也就是说,在上例中,改变order1.items并不会影响order2.items了。因为内存中有两个一样的items。

如果实现深克隆?

一个方法自然是重写clone方法,添加如order.items=(LineItems)items.clone()的语句,也就是人为地添加对引用对象的复制。这个方法的缺点是如果引用对象有很多,或者说引用套引用很多重,那么太麻烦了。业界常用的方法是使用串行化然后反串行化的方法来实现深克隆。由于串行化后,对象写到流中,所有引用的对象都包含进来了,所以反串行化后,对等于生成了一个完全克隆的对象。绝!

这个方法的要求是对象(包括被引用对象)必须事先了Serializable接口,否则就要用transient关键字将其排除在复制过程中。
作者: 乐峰    时间: 2012-6-12 23:32
简单说就是复制对象,得到一个对象的副本,包含的属性值与原对象的相同。
Object 的 clone() 是 受保护的,且 它本身 不实现 Cloneable接口,所以 当一个类没有实现 Cloneable 接口,就直接调用  super.clone() ——这时是调用的Object的clone()  ,是不可以的。会导致抛出 CloneNotSupportedException 异常,需要先实现 Cloneable 接口。
如:     class A implements Cloneable {  public Object clone() { Object obj=null; obj = super.clone(); return obj }  }
             main(...){   A a = new A();    A b = (A)a.clone();    }

影子克隆: 若还有个类 class B{..}  当在A 类中有属性 public B b = new B();在克隆后,,会发现,A类中的 一些基本属性 能被真正克隆,即 在改变 克隆得到的对象里的基本属性值时,,原对象不改变,而 在改变 B对象中的属性值 时,,原对象也 改变了,这样,这个克隆  就不是真正的克隆了。
深度克隆: 让 class B也实现Cloneable接口,,实现 clone(), 在A 调用了super.clone()后,,也把它的属性 b = (Clone)b.clone();
                 这样引用对象和基本对象都 实现了 克隆。
不能克隆的类:  String,Integer,Double等等,它们没有实现 Cloneable接口,且 是final 修饰的类。


作者: 江南    时间: 2012-6-12 23:45
通俗理解:把这个对象的属性赋值给另外一个对象,实际编程过程中,我们常常要遇到这种情况把一个个对象传到另外方法中 可能会造出对这个对象值的修改 处于安全考虑会把这个对象 复制一份出来把这个复制出来的对象在传过去就不会对原有对象的属性修改,这也叫安全拷贝
例如有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B 任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。在Java语言中,用简单的赋值语句是不能满足这种需 求的。要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单,也是最高效的手段。






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2