本文共 5760 字,大约阅读时间需要 19 分钟。
即复制一个对象出来,他存在Object
类中,是一个本地方法,并且修饰符是protected
,所以他是可以让其子类实现自己的clone方法的
protected native Object clone() throws CloneNotSupportedException;
使用clone方法,需要被clone的对象实现Cloneable
接口,否则会有异常CloneNotSupportedException
,但是实现的这个接口中并没有实现任何方法,只是一个标记接口的作用
public class TargetClass implements Cloneable{ int id; long timestamp; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() {...}}
然后测试
public class Tests { public static void main(String[] args) throws CloneNotSupportedException { TargetClass target = new TargetClass(); target.id = 1; target.timestamp = System.currentTimeMillis(); TargetClass target2 = target; Object o = target.clone(); System.out.println(target); System.out.println(target2); System.out.println(o); target.id = 2; System.out.println("--------------------"); System.out.println(target); System.out.println(target2); System.out.println(o); }}
结果
TargetClass{id=1, timestamp=1548131568371}TargetClass{id=1, timestamp=1548131568371}TargetClass{id=1, timestamp=1548131568371}--------------------TargetClass{id=2, timestamp=1548131568371}TargetClass{id=2, timestamp=1548131568371}TargetClass{id=1, timestamp=1548131568371}
=
直接赋值对象的时候,是直接将引用赋值给此对象的,所以当target对象更改的时候,target2对象也会受到影响,他俩的关系就类似是这样的我们也可以将toString注释掉,查看他们的地址值,发现可以证实我们的说法是正确的
TargetClass@677327b6TargetClass@677327b6TargetClass@14ae5a5--------------------TargetClass@677327b6TargetClass@677327b6TargetClass@14ae5a5
我们再看一个例子,这时候TargetClass对象发生一点改变
public class TargetClass implements Cloneable{ int id; long timestamp; InnerClass innerClass; class InnerClass{ long innerClassNumber; public InnerClass(long innerClassNumber) { this.innerClassNumber = innerClassNumber; } } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() {...}}
测试
public static void main(String[] args) throws CloneNotSupportedException { TargetClass target = new TargetClass(); target.id = 1; target.timestamp = System.currentTimeMillis(); target.innerClass = new TargetClass().new InnerClass(1); TargetClass target2 = target; Object o = target.clone(); System.out.println(target); System.out.println(target2); System.out.println(o); target.id = 2; target.innerClass.innerClassNumber = 2; System.out.println("--------------------"); System.out.println(target); System.out.println(target2); System.out.println(o);}
结果
TargetClass{id=1, timestamp=1548132881258, innerClass=1}TargetClass{id=1, timestamp=1548132881258, innerClass=1}TargetClass{id=1, timestamp=1548132881258, innerClass=1}--------------------TargetClass{id=2, timestamp=1548132881258, innerClass=2}TargetClass{id=2, timestamp=1548132881258, innerClass=2}TargetClass{id=1, timestamp=1548132881258, innerClass=2}
=
操作,那不就是拿出innerClassNumber
吗,其实不是的,只是将InnerClass对象的引用赋值给了新clone的对象,所以造成了三个实例引用一个innerClass实例,就造成了,更改一个值,三个实例收到影响为了避免上面的都受影响的情况,即clone出来的对象不受target实例改变的影响,我们就得再次重写实现TargetClass的clone方法
@Overrideprotected Object clone() throws CloneNotSupportedException { TargetClass targetClass = new TargetClass(); targetClass.id = this.id; targetClass.timestamp = this.timestamp; targetClass.innerClass = this.new InnerClass(this.innerClass.innerClassNumber); return targetClass;}
如上就可以实现了clone出来的对象不受target实例改变的影响了,测试结果如下
TargetClass{id=1, timestamp=1548134335063, innerClass=1}TargetClass{id=1, timestamp=1548134335063, innerClass=1}TargetClass{id=1, timestamp=1548134335063, innerClass=1}--------------------TargetClass{id=2, timestamp=1548134335063, innerClass=2}TargetClass{id=2, timestamp=1548134335063, innerClass=2}TargetClass{id=1, timestamp=1548134335063, innerClass=1}
更简单的一种实现InnerClass的clone方法,就是InnerClass也实现Cloneable接口,然后更改TargetClass的clone方法
public class TargetClass implements Cloneable{ int id; long timestamp; InnerClass innerClass; class InnerClass implements Cloneable{ long innerClassNumber; public InnerClass(long innerClassNumber) { this.innerClassNumber = innerClassNumber; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } @Override protected Object clone() throws CloneNotSupportedException { TargetClass clazz = (TargetClass) super.clone(); clazz.innerClass = (InnerClass) innerClass.clone(); return clazz; } @Override public String toString() {...}}
A->B->C->D->...
,那么我们就需要在A的clone方法中实现对B.C.D的深层引用clone,所以在复杂业务中实现深克隆并不是很容易的,所以深克隆即完全克隆,基本上是不可能实现的转载地址:http://nyuoo.baihongyu.com/