引用拷贝、对象拷贝、浅拷贝、深拷贝 到底是什么【详细例子介绍】

您所在的位置:网站首页 java引用和对象的区别是什么 引用拷贝、对象拷贝、浅拷贝、深拷贝 到底是什么【详细例子介绍】

引用拷贝、对象拷贝、浅拷贝、深拷贝 到底是什么【详细例子介绍】

2024-06-23 05:06| 来源: 网络整理| 查看: 265

首先要知道的:

Java的数据类型分为基本数据类型和引用数据类型。

拷贝一个对象,可以使用 Cloneable接口的clone()方法。

对象拷贝分为 浅拷贝 和 深拷贝,这两种拷贝都是从引用拷贝 引出的。

通过下面的例子你就可以明白这三者的区别了。

1、引用拷贝

引用拷贝 简单的说就是通过 = 地址赋值。

class TestClone { public static void main(String[] args) throws CloneNotSupportedException { String[] hobbies = new String[]{"打篮球", "码代码"}; Student studentA = new Student(1, "HaC", hobbies); System.out.println("------------引用拷贝----------------"); Student studentB = studentA; //复制引用,这是对象地址赋值 studentB.setId(2); //studentA studentB 都是指向同一个地址 hobbies[0] = "看电影"; System.out.println("studentA:" + studentA); System.out.println("studentC:" + studentB); System.out.println("studentA == studentB 的结果:"+(studentA == studentB)); } } @AllArgsConstructor @Data public class Student implements Cloneable { int id; String name; String[] hobbies; }

输出:

------------引用拷贝---------------- studentA:Student(id=2, name=HaC, hobbies=[看电影, 码代码]) studentC:Student(id=2, name=HaC, hobbies=[看电影, 码代码]) studentA == studentB 的结果:true

这里其实是复制了一个地址指向堆,studentA、studentC 两个引用都是指向同一个地址, 这就叫做引用拷贝。

2、浅拷贝

Cloneable接口提供了一个clone() 方法进行 对象拷贝 ,我们可以通过实现clone()方法实现浅拷贝或者深拷贝。

浅拷贝可以创建一个对象的副本,把基本数据类型和final修饰的数据类型 复制一份,但是如果是引用数据类型,只能复制地址。

class TestClone { public static void main(String[] args) throws CloneNotSupportedException { String[] hobbies = new String[]{"打篮球", "码代码"}; Student studentA = new Student(1, "HaC", hobbies); System.out.println("------------浅拷贝----------------"); Student studentC = (Student) studentA.clone(); System.out.println("studentA:" + studentA); System.out.println("studentC:" + studentC); System.out.println("studentA == studentC 的结果:" + (studentA == studentC)); studentA.setName("哈希"); hobbies[0] = "看电影"; System.out.println("studentA:" + studentA); System.out.println("studentC:" + studentC); } } @AllArgsConstructor @Data public class Student implements Cloneable { int id; String name; String[] hobbies; @Override protected Object clone() throws CloneNotSupportedException { //浅拷贝 return super.clone(); } }

输出:

------------浅拷贝---------------- studentA:Student(id=1, name=HaC, hobbies=[打篮球, 码代码]) studentC:Student(id=1, name=HaC, hobbies=[打篮球, 码代码]) studentA == studentC 的结果:false studentA:Student(id=1, name=哈希, hobbies=[看电影, 码代码]) studentC:Student(id=1, name=HaC, hobbies=[看电影, 码代码])

可以看到浅拷贝之后:studentA 和 studentC是两个不同的地址了,说明clone()方法重新拷贝了一份对象,所以 studentA.setName("哈希"); 仅仅是修改了 studentA 对象。

但是 hobbies[0] = "看电影"; 却是联动的,对 studentA 、studentC 两个对象都是有有影响的,说明这个hobbies字段是个地址拷贝。

3、深拷贝

浅拷贝是无法把引用对象的值也拷贝的,只是拷贝了地址。

所以如果你要把地址对应的 值也拷贝一份,可以使用深拷贝,实现的原理就是 在clone()方法 再拷贝一份你需要的对象。

class TestClone { public static void main(String[] args) throws CloneNotSupportedException { String[] hobbies = new String[]{"打篮球", "码代码"}; Student studentA = new Student(1, "HaC", hobbies); System.out.println("------------深拷贝----------------"); Student studentC = (Student) studentA.clone(); System.out.println("studentA:" + studentA); System.out.println("studentC:" + studentC); System.out.println("studentA == studentC 的结果:" + (studentA == studentC)); studentA.setName("哈希"); hobbies[0] = "看电影"; System.out.println("studentA:" + studentA); System.out.println("studentC:" + studentC); } } @AllArgsConstructor @Data public class Student implements Cloneable { int id; String name; String[] hobbies; @Override protected Object clone() throws CloneNotSupportedException { // 深拷贝,现在将String[]复制一份并重新set进来 Student student = (Student) super.clone(); student.setHobbies(student.getHobbies().clone()); return student; } }

输出:

------------深拷贝---------------- studentA:Student(id=1, name=HaC, hobbies=[打篮球, 码代码]) studentC:Student(id=1, name=HaC, hobbies=[打篮球, 码代码]) studentA == studentC 的结果:false studentA:Student(id=1, name=哈希, hobbies=[看电影, 码代码]) studentC:Student(id=1, name=HaC, hobbies=[打篮球, 码代码])

深拷贝会 毫无保留地把所有对象都拷贝一份出来,然后修改就是自己的对象。

总结:

1、深拷贝和浅拷贝都是对象拷贝,引用拷贝只是赋值了一个地址,并不是真正的对象的值。

2、浅拷贝

浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址

(1) 对于基本数据类型、final修饰 的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个。

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

3、深拷贝

深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存。

深拷贝把要复制的对象所引用的对象都复制了一遍

区别:

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。

深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3