1. 浅复制:只复制了对象的引用,实际对应的还是一个对象实例,例如下例中的Address
1 /* 2 * 浅复制 3 */ 4 5 class Address2 { 6 private String add; 7 8 public String getAdd() { 9 return add; 10 } 11 12 public void setAdd(String add) { 13 this.add = add; 14 } 15 16 } 17 18 class Student2 implements Cloneable{ 19 private int number; 20 21 private Address2 addr; 22 23 public Address2 getAddr() { 24 return addr; 25 } 26 27 public void setAddr(Address2 addr) { 28 this.addr = addr; 29 } 30 31 public int getNumber() { 32 return number; 33 } 34 35 public void setNumber(int number) { 36 this.number = number; 37 } 38 39 @Override 40 public Object clone() { 41 Student2 stu = null; 42 try{ 43 stu = (Student2)super.clone(); 44 }catch(CloneNotSupportedException e) { 45 e.printStackTrace(); 46 } 47 return stu; 48 } 49 } 50 public class CopyTest2 { 51 52 public static void main(String args[]) { 53 54 Address2 addr = new Address2(); 55 addr.setAdd("杭州市"); 56 Student2 stu1 = new Student2(); 57 stu1.setNumber(123); 58 stu1.setAddr(addr); 59 60 Student2 stu2 = (Student2)stu1.clone(); 61 62 System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd()); 63 System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd()); 64 addr.setAdd("合肥市"); 65 stu1.setAddr(addr); 66 System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd()); 67 System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd()); 68 } 69 }
2. 深复制:复制另一个实例对象,两者没有任何交叉的关系
1 /* 2 * 深复制 3 */ 4 class Address implements Cloneable { 5 private String add; 6 7 public String getAdd() { 8 return add; 9 } 10 11 public void setAdd(String add) { 12 this.add = add; 13 } 14 15 @Override 16 public Object clone() { 17 Address addr = null; 18 try{ 19 addr = (Address)super.clone(); 20 }catch(CloneNotSupportedException e) { 21 e.printStackTrace(); 22 } 23 return addr; 24 } 25 } 26 27 class Student implements Cloneable{ 28 private int number; 29 30 private Address addr; 31 32 public Address getAddr() { 33 return addr; 34 } 35 36 public void setAddr(Address addr) { 37 this.addr = addr; 38 } 39 40 public int getNumber() { 41 return number; 42 } 43 44 public void setNumber(int number) { 45 this.number = number; 46 } 47 48 @Override 49 public Object clone() { 50 Student stu = null; 51 try{ 52 stu = (Student)super.clone(); //浅复制 53 }catch(CloneNotSupportedException e) { 54 e.printStackTrace(); 55 } 56 stu.addr = (Address)addr.clone(); //深度复制 57 return stu; 58 } 59 } 60 public class CopyTest { 61 62 public static void main(String args[]) { 63 64 Address addr = new Address(); 65 addr.setAdd("杭州市"); 66 Student stu1 = new Student(); 67 stu1.setNumber(123); 68 stu1.setAddr(addr); 69 70 Student stu2 = (Student)stu1.clone(); 71 72 System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd()); 73 System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd()); 74 75 addr.setAdd("西湖区"); 76 77 System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd()); 78 System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd()); 79 } 80 }
3. 观察两者的区别不难发现,只一点浅复制的Address类没有继承Cloneable接口,进而实现clone()方法。默认的是java.lang.Object的clone()方法。
4. 对象的序列化也能实现深复制。但需要对象中的每一种成分都是可序列化的才行。
5. Java中参数传递:值传递和引用传递的简单总结
- 对象就是传引用
- 原始类型就是传值
- String类型因为没有提供自身修改的函数,每次操作都是新生成一个String对象,所以要特殊对待。可以认为是传值。