天天看点

java 深拷贝和浅拷贝

浅拷贝首先会创建一个新的对象,这个对象和原始对象属性值相同。如果原始对象是数值类型对象,那么拷贝的就是基本类型的值;如果拷贝的对象是引用类型的话,拷贝的就是原始对象的地址,可以说浅拷贝就相当于是一个指针指向被拷贝对象的地址。

①对于基础类型的成员对象,浅拷贝会以值传递的方式,直接将属性值赋值给新的对象。修改原始对象的成员或者修改新对象的成员,不会另外一方的值。

②对于引用类型,比如数组或者类对象,因为引用类型是引用传递,所以浅拷贝只是把内存地址赋值给了成员变量,它们指向了同一内存空间。改变其中一个,会对另外一个也产生影响。

实现浅拷贝对象的类,要实现Cloneable接口

测试类

运行结果

可以看出对新复制出对象的基本数据类型成员进行修改,并不会改变原有对象中的成员,但是对引用类型成员进行修改,则原始对象中的成员也会被改变。

浅拷贝结构图大致如下:

java 深拷贝和浅拷贝

现在将

修改为

可以看到结果

可以看出,对象赋值仅仅是将引用赋值给了新的对象,这两个对象指向同一的内存地址,修改其中一个对象的成员,另一个也会随之修改。

浅拷贝拷贝的对象中的引用类型指向的是同一块堆内存地址。这会使我们修改拷贝对象内容时会有数据安全隐患。深拷贝,在拷贝引用类型成员变量时,为引用类型的数据成员另辟了一个独立的内存空间,实现真正内容上的拷贝。

①对于引用类型,深拷贝都会新建一个对象空间来存储这些拷贝的引用,这样就会使它们指向不同的内存地址改变其中一个,不会影响另外一个。

②对于有多层对象的,每个对象都需要实现 ​<code>​Cloneable​</code>​ 并重写 ​<code>​clone()​</code>​ 方法,进而实现了对象的串行层层拷贝

③由于得为每一个引用类型成员开辟新的空间,相比较于浅拷贝,深拷贝将会更加消耗内存空间,并且花费更多时间。

修改subject来,使其也实现​<code>​Cloneable​</code>​ 并重写 ​<code>​clone()​</code>​

重写student的clone方法,拷贝引用成员subject

测试结果

可以看出,深拷贝后,不管是基础数据类型还是引用类型的成员变量,修改后都不会影响原始对象

深拷贝的结构图大致如下:

java 深拷贝和浅拷贝