最近看一些书籍,深拷贝和浅拷贝的字样,总是浮现在眼前,于是乎整理了一下,关于java的深浅拷贝原理和实现。

    1. 什么是深/浅拷贝?

    浅拷贝:对目标对象的基本数据类型值的复制和引用类型的地址的复制;

    深拷贝:对目标对象的基本数据类型值的复制以及应用类型值复制(专业点称之为动态内存)。

    从概念上分很难以理解,下图列出了两者的区别:

    1)浅拷贝

    

    上图中,左侧是原始对象(基本数据类型、引用类型),但使用浅拷贝方式生成一个新对象,使得新对象的基本类型数值与原始对象一致,但是引用数据类型会指向原始对象引用类型,因此当原始对象和浅拷贝对象任何一方修改了引用类型的值,那么另一方也会发生改变。因为两者指向同一个对象。

    2)深拷贝

    

    从上图可以发现原始对象和深拷贝对象两者没用引用连接关系。深拷贝实际执行的是生成一个新的对象,基本数据类型与原始对象一直,引用数据类型通过原始对象引用数据类型值构造的新对象。通俗点说就是深拷贝对象的引用数据与原始对象的引用数据值相同,但不是同一个对象,不指向同一块地址。

    2. java实现深/拷贝

public class Student {		private String name;		private int age;		public Student(String name, int age){		this.name = name;		this.age = age;	}	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public int getAge() {		return age;	}	public void setAge(int age) {		this.age = age;	}	}public class Classes implements Cloneable{	private String className;		private Student student;		public Classes(String className, Student student){		this.className = className;		this.student = student;	}		/**	 * 默认实现的是浅拷贝	 */	@Override	public Object clone() throws CloneNotSupportedException {		return super.clone();	}		/**	 * 深拷贝 : 新建立一个对象	 * @return	 */	public Classes deepCopy() {		Classes classes = new Classes(this.getClassName(), new Student(this.getStudent().getName(), this.getStudent().getAge()));		return classes;	}	public String getClassName() {		return className;	}	public void setClassName(String className) {		this.className = className;	}	public Student getStudent() {		return student;	}	public void setStudent(Student student) {		this.student = student;	}}// 测试代码public class TestCopy {	@Test	public void testShallowCopy() throws CloneNotSupportedException{		Classes classes = new Classes("信计091", new Student("wangzp", 23));		// 浅拷贝,新创建一个对象,然后拷贝基本数据类型数值,引用类型地址		Classes classes1 = (Classes)classes.clone();		System.out.println(classes.getStudent() == classes1.getStudent());//true	}		@Test	public void testDeepCopy(){		Classes classes = new Classes("信计091", new Student("wangzp", 23));		Classes classes1 = classes.deepCopy();		System.out.println(classes1.getStudent() == classes.getStudent());//false	}	}

    

    3. 深/浅拷贝的差异

    从2中代码实现,可以发现深拷贝是重新构造对象的过程,因此效率并不是很好。而浅拷贝由于拷贝对象与原始对象之间引用对象是共享的,因此容易导致任意一方修改引用类型属性,而另一方也修改了,容易导致错误的发生。

    一般而言,如果原始对象变量多为基本数据类型,且引用类型不常修改,建议使用浅拷贝;反之建议使用深拷贝。