=、浅拷贝和深拷贝的区分
1 package copy_types; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * '=' symbol copy 8 * @author ASUS 9 * 10 */ 11 12 class ClassA{ 13 int a = 1;//值类型 14 15 List<String> list;//引用类型 16 17 public ClassA(){ 18 list = new ArrayList<>(); 19 list.add("string 1"); 20 list.add("string 2"); 21 } 22 23 public void print(){ 24 System.out.println("-----"+this.toString()+"-----"); 25 System.out.println("a = " + a); 26 System.out.println("list = " + list); 27 } 28 29 public void change(){ 30 this.a = 2; 31 this.list.clear(); 32 } 33 } 34 35 public class EqualSymbol { 36 public static void main(String args[]){ 37 ClassA A = new ClassA(); 38 ClassA B = A; 39 40 A.print(); 41 B.print(); 42 43 B.change(); 44 45 A.print(); 46 B.print(); 47 } 48 }
打印结果:
-----copy_types.ClassA@327800e9----- a = 1 list = [string 1, string 2] -----copy_types.ClassA@327800e9----- a = 1 list = [string 1, string 2]
-----copy_types.ClassA@327800e9----- a = 2 list = [] -----copy_types.ClassA@327800e9----- a = 2 list = []
从结果可以看出经过等号“=”复制之后,他们所指向的都是一个对象,所以不管类里面的对象是值类型还是引用类型,一旦修改,处处修改。
浅拷贝:
1 package copy_types; 2 3 /** 4 * 自定义一个类(作为自定义的引用类型的测试) 5 * @author ASUS 6 * 7 */ 8 public class CommonClass { 9 10 int a = 1; 11 12 public int getA() { 13 return a; 14 } 15 16 public void setA(int a) { 17 this.a = a; 18 } 19 20 }
package copy_types; import java.util.ArrayList; import java.util.List; /** * 浅拷贝 * @author ASUS * */ class ClassB implements Cloneable{ int a = 1;//值类型 String str; List<String> list;//引用类型 CommonClass cc; public ClassB(){ list = new ArrayList<>(); list.add("string 1"); list.add("string 2"); str = "str1"; cc = new CommonClass(); } public void print(){ System.out.println("-----"+this.toString()+"-----"); System.out.println("a = " + a); System.out.println("str = " + str); System.out.println("list = " + list); System.out.println("cc = " + cc.getA()); } public void change(){ this.a = 2; this.list.clear(); this.str = "str2"; cc.setA(100); } @Override protected Object clone() { // TODO Auto-generated method stub Object o = null; try { o = super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return o; } } public class ShallowCopy { public static void main(String args[]){ ClassB b = new ClassB(); ClassB changeB = (ClassB) b.clone(); changeB.change(); b.print(); changeB.print(); } }
结果:
-----copy_types.ClassB@44cae5b8----- a = 1 str = str1 list = [] cc = 100 -----copy_types.ClassB@17823918----- a = 2 str = str2 list = [] cc = 100
由此可以看出b和changeB指向的是不通地址的对象,此时各自的值类型各自拥有,值类型的修改互相不影响,但是,里面的引用类型的仍然指向同一个对象,一个修改,处处修改。例如上面的cc中的值类型a被修改成了100,而由于b对象的cc和changeB对象的cc指向的是同一个对象,那么既然changeB中的cc.a被修改了,b.cc.a也同样改变了。
深拷贝:
简单做个说明,深拷贝时从浅拷贝引发的,浅拷贝只是一层的clone,而深拷贝要对类中的引用类型进行clone,比如让CommonClass实现Cloneable接口,并且实现clone接口,在原来的类中调用clone来复制对象。请看代码:
1 package copy_types; 2 3 class CClass implements Cloneable{ 4 5 int a = 0; 6 7 public int getA() { 8 return a; 9 } 10 11 public void setA(int a) { 12 this.a = a; 13 } 14 15 @Override 16 protected Object clone() { 17 // TODO Auto-generated method stub 18 Object o = null; 19 try { 20 o = super.clone(); 21 } catch (CloneNotSupportedException e) { 22 // TODO Auto-generated catch block 23 e.printStackTrace(); 24 } 25 return o; 26 } 27 } 28 29 class DeepCopy implements Cloneable{ 30 CClass dc; 31 public DeepCopy(){ 32 dc = new CClass(); 33 } 34 35 public void print(){ 36 System.out.println(dc.toString()+"\n"+dc.getA()); 37 } 38 39 public void change(){ 40 dc.setA(1000); 41 } 42 43 @Override 44 protected Object clone() { 45 // TODO Auto-generated method stub 46 DeepCopy o = null; 47 try { 48 o = (DeepCopy) super.clone(); 49 o.dc = (CClass) dc.clone(); 50 } catch (CloneNotSupportedException e) { 51 // TODO Auto-generated catch block 52 e.printStackTrace(); 53 } 54 return o; 55 } 56 } 57 58 public class DeepClone { 59 60 public static void main(String args[]){ 61 DeepCopy d = new DeepCopy(); 62 DeepCopy e = (DeepCopy) d.clone(); 63 64 e.change(); 65 66 d.print(); 67 e.print(); 68 } 69 70 }
输出:
copy_types.CClass@397b6178 0 copy_types.CClass@533c2ac3 1000
由此可以看出里面的引用类型对象属于不同的对象,一个修改不影响另一个,简而言之,深拷贝就是要将浅拷贝“进行到底”。