Java 对象克隆
首先,我们需要知道的是,什么是对象克隆?对象克隆是当程序运行时,可能需要一个新对象,用来保存当前对象的状态,并且新的对象与当前对象没有任何关联,即我改变了新对象属性的值,而当前对象没有发生改变。而这新的对象,就是对当前对象的克隆,或者说拷贝。 要完成对象克隆,有以下要求: ? 1. 新的对象与当前对象值相同 ? ? ?2. 新的对象与当前对象的引用地址不同 ? 要实现对象克隆,有以下步骤: 1. 对要被对象克隆的对应类继承Cloneable接口,并重载clone方法,将访问权限改成public ? ? ?2. 将当前对象的clone方法赋值给新的对象,完成对象克隆。 public class Test implements Cloneable{ public int a; public int b; private int c; private int d; public String aa; private String bb; public TestIn testIn = new TestIn(); public TestIns testIns = new TestIns(); @Override public Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); } public Test(){} public Test(int a,int b,int c,int d){ this.a=a; this.b=b; this.c=c; this.d=d; } private Test(int c,int d){ this.c=c; this.d=d; } public int getA() { return a; } public void setA(int a) { this.a = a; } public int getB() { return b; } public void setB(int b) { this.b = b; } public int getC() { return c; } public void setC(int c) { this.c = c; } public int getD() { return d; } public void setD(int d) { this.d = d; } private void A(){ System.out.println("哈哈哈"); } public void B(){ System.out.println("fdsa"); } public String getAa() { return aa; } public void setAa(String aa) { this.aa = aa; } public String getBb() { return bb; } public void setBb(String bb) { this.bb = bb; } @Override public String toString() { return "Test [a=" + a + ",b=" + b + ",c=" + c + ",d=" + d + ",aa=" + aa + ",bb=" + bb + "]"; } class TestIn{ public String test_a; public int test_b; } class TestIns{ public String test_a; public int test_b; } } ? Test test_1 = new Test(); ?以上代码的运行结果为: ++++++++++拷贝(克隆)+++++++++++ ----------赋值前---------- test_1:Test [a=2,b=0,c=0,d=0,aa=null,bb=null] test_2:Test [a=2,bb=null] ----------赋值基本类型---------- test_1:Test [a=2,bb=null] test_2:Test [a=4,bb=null] 类是否引用同个地址:false 这样,我们就实现了对象的克隆,当然,仅仅只是针对当前对象基本类型的克隆,这种对象克隆我们称之为浅克隆。 而如果要实现基本数据类型以及引用类型的克隆,就需要深克隆。 在test类中,你们也可以看到,有两个类的对象,一个是TestIn类,一个是TestIns类,并且都初始化了,然而在浅克隆的情况下,他们指向的地址是一致的 System.out.println("类的引用类TestIn是否引用同个地址:"+(test_1.testIn == test_2.testIn));
System.out.println("类的引用类TestIns是否引用同个地址:"+(test_1.testIns == test_2.testIns));
其运行结果: 类的引用类TestIn是否引用同个地址:true 类的引用类TestIns是否引用同个地址:true 如何实现深克隆呢,其实实现深克隆和实现浅克隆的原理差不多,步骤如下: 1.被克隆的对象对应类要继承Cloneable接口,并重载clone方法 ? ? ? ?2.若被克隆的对象里,有属性为被克隆的对象,则需要重写clone方法 ? ? ? ?3.?将当前对象的clone方法赋值给新的对象,完成对象深克隆。 以下代码我重写了Test的clone方法,并让对应类TestIns继承了Cloneable接口,重载clone方法 public class Test implements Cloneable{ public int a; public int b; private int c; private int d; public String aa; private String bb; public TestIn testIn = new TestIn(); public TestIns testIns = new TestIns(); @Override public Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub Test test = (Test)super.clone(); test.testIns =(TestIns) this.testIns.clone(); return test; } public Test(){} public Test(int a,bb=" + bb + "]"; } class TestIn{ public String test_a; public int test_b; } class TestIns implements Cloneable{ public String test_a; public int test_b; @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); } } } System.out.println("类的引用类TestIn是否引用同个地址:"+(test_1.testIn == test_2.testIn));
System.out.println("类的引用类TestIns是否引用同个地址:"+(test_1.testIns == test_2.testIns));
运行效果如下: 类的引用类TestIn是否引用同个地址:true 类的引用类TestIns是否引用同个地址:false 有兴趣的可以去了解一下,为什么克隆有浅克隆和深克隆的区别:https://www.jianshu.com/p/b597f3e8269a? 总结:无论是浅克隆还是深克隆,都需要将对应类继承Cloneable接口,并重载或者重写clone方法;浅克隆,只能克隆类的基本类型,而深克隆则可以克隆基本基本类型以及引用类型。 public class TestMain{ public static void main(String[] args){ Test test_1 = new Test(); Test test_2 = test_1; System.out.println("++++++++++引用+++++++++++"); System.out.println("----------赋值前----------"); System.out.println("test_1:"+test_1); System.out.println("test_2:"+test_2); test_2.setA(2); System.out.println("----------赋值后----------"); System.out.println("test_1:"+test_1); System.out.println("test_2:"+test_2); System.out.println("类是否引用同个地址:"+(test_1 == test_2)); try { test_2 = (Test) test_1.clone(); System.out.println("r++++++++++拷贝(克隆)+++++++++++"); System.out.println("----------赋值前----------"); System.out.println("test_1:"+test_1); System.out.println("test_2:"+test_2); test_2.setA(4); System.out.println("----------赋值基本类型----------"); System.out.println("test_1:"+test_1); System.out.println("test_2:"+test_2); System.out.println("类是否引用同个地址:"+(test_1 == test_2)); System.out.println("类的引用类TestIn是否引用同个地址:"+(test_1.testIn == test_2.testIn)); System.out.println("类的引用类TestIns是否引用同个地址:"+(test_1.testIns == test_2.testIns)); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |