Java 的深拷贝和浅拷贝,其实现方式正是通过调用 Object 类的 clone() 方法来完成。源码为:
protected native Object clone() throws CloneNotSupportedException;
这是一个用 native 关键字修饰的方法,关于native关键字有一篇博客专门有介绍,不理解也没关系,只需要知道用 native 修饰的方法就是告诉操作系统,这个方法我不实现了,让操作系统去实现。具体怎么实现我们不需要了解,只需要知道 clone方法的作用就是复制对象,产生一个新的对象。
那么这个新的对象和原对象是什么关系呢?
- 克隆对象和原对象不是同一个对象,占用不同的内存地址
- 克隆对象和原对象应该具有相同的类型,但它不是强制性的
- 克隆对象和原对象使用equals()方法比较应该是相等的,但它不是强制性的
让我们在学习之前,先来区别一下深拷贝与浅拷贝:
成员引用:类中为引用类型的成员
浅拷贝:原对象和克隆对象不同,但对象内的成员引用相同。深拷贝:原对象和克隆对象不同,且对象内的成员引用也不同 (
不同:不是同一个对象,所占内存地址不同。)
举个巧妙的例子来说:
浅拷贝:一个男孩拥有一台电脑,通过浅克隆后,成了两个男孩,但他们共享一台电脑。
深拷贝:一个男孩拥有一台电脑,通过深克隆后,成了两个男孩,他们拥有各自的电脑
浅拷贝:
浅拷贝在拷贝一个对象时,对对象的基本数据类型的成员变量进行拷贝,但对引用类型的成员变量只进行引用的传递,并没有创建一个新的对象。也就是说,浅拷贝只是传递了引用类型成员变量的地址指向,新的对象并没有对引用数据类型创建内存空间。因此,当对引用类型的内容进行修改时,会影响被拷贝的对象。在Java中,clone方法是一个典型的浅拷贝实现。
深拷贝:
深拷贝在拷贝一个对象时,除了对基本数据类型的成员变量进行拷贝外,对引用类型的成员变量也会进行拷贝,并创建一个新的对象来保存引用类型的成员变量。这意味着深拷贝会对整个对象图进行拷贝,包括对象的所有基本数据类型的成员变量值和所有引用数据类型的成员变量所引用的对象,直到该对象可达的所有对象。因此,两个引用对象分别指向两个完全不同的对象,且两个引用对象的引用也分别指向两个不同的对象。在Java中,实现深拷贝的一种常见方法是通过序列化和反序列化对象。
总的来说:
深拷贝和浅拷贝的主要区别在于如何处理引用类型的成员变量。深拷贝会创建新的对象来保存引用类型的成员变量,而浅拷贝只是传递引用。因此,在选择使用深拷贝还是浅拷贝时,需要根据具体的需求和场景来决定。