当前位置: 代码迷 >> 综合 >> Java回炉重铸(二)为什么要使用Clone?深拷贝和浅拷贝的区别有哪些?
  详细解决方案

Java回炉重铸(二)为什么要使用Clone?深拷贝和浅拷贝的区别有哪些?

热度:54   发布时间:2023-09-05 19:21:46.0

为什么要使用Clone?深拷贝和浅拷贝的区别有哪些?

? 1.首先明白什么是引用?

? 当我们在创建对象时,首先在堆区进行内存的分配,然后调用构造方法进行初始化。对象的实例保存在堆中,对象的引用保存在栈中。引用就好像c语言中的指针一样保存着对象实例的地址,我们实际通过操作对象的引用来操作对象。

Java回炉重铸(二)为什么要使用Clone?深拷贝和浅拷贝的区别有哪些?

? 2. clone帮助我们解决了什么问题?为什么要进行clone?

    class Person{String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}}public class Test3 {public static void main(String[] args) {Person p1 = new Person("xiaowang",12);System.out.println(p1.getAge()+p1.getName());Person p2 = p1;p2.age = 13;System.out.println(p1.getAge()+p1.getName());}}

现有一个Person类,类的成员变量有name,age

首先new 一个 Person p1对象,通过有参构造方法赋值它的name=“xiaowang",age = 12

把p1对象赋值给p2对象。我们修改p2对象的age时,奇怪的现象发生了。控制台输出了

    12xiaowang13xiaowang

此时p1对象的age也发生了改变

为什么?因为通过 == 赋值其实是赋值的是对象引用,此时p1,p2都指向了同一块内存空间,对其中一个的修改都会影响所有的指向该内存空间引用的对象。clone就是帮助我们解决这种引用赋值问题的

? 3 .什么是深clone?什么是浅clone?

? 由于 age 是基本数据类型, 那么对它的拷贝没有什么疑议,直接将一个 4 字节的整数值拷贝过来就行。但是 name是 String 类型的, 它只是一个引用, 指向一个真正的 String 对象,那么对它的拷贝有两种方式: 直接将原对象中的 name 的引用值拷贝给新对象的 name 字段, 或者是根据原 Person 对象中的 name 指向的字符串对象创建一个新的相同的字符串对象,将这个新字符串对象的引用赋给新拷贝的 Person 对象的 name 字段。这两种拷贝方式分别叫做浅拷贝和深拷贝。深拷贝和浅拷贝的原理如下图所示:

Java回炉重铸(二)为什么要使用Clone?深拷贝和浅拷贝的区别有哪些?
下面通过代码进行验证。如果两个 Person 对象的 name 的地址值相同, 说明两个对象的 name 都指向同一个
String 对象,也就是浅拷贝, 而如果两个对象的 name 的地址值不同, 那么就说明指向不同的 String 对象, 也就是在拷贝 Person 对象的时候, 同时拷贝了 name 引用的 String 对象, 也就是深拷贝。验证代码如下:

我们来到程序测试一下 clone的person对象是深拷贝,还是浅拷贝?

Person p1 = new Person("xiaowang",12);
Person p2 = (Person) p1.clone();
System.out.println(p1.getName()==p2.getName());output 
--
true

输出为true ,说明name指向的是同一块内存空间,这种拷贝方式是浅拷贝。

? 4.如何进行深拷贝:
由上一节的内容可以得出如下结论:如果想要深拷贝一个对象,这个对象必须要实现 Cloneable 接口,实现 clone
方法,并且在 clone 方法内部,把该对象引用的其他对象也要 clone 一份,这就要求这个被引用的对象必须也要实现Cloneable 接口并且实现 clone 方法。那么,按照上面的结论,实现以下代码 Body 类组合了 Head 类,要想深拷贝Body 类,必须在 Body 类的 clone 方法中将 Head 类也要拷贝一份。代码如下:

?

 class Body implements Cloneable{public Head head;public Body() {}public Body(Head head) {this.head = head;}@Overrideprotected Object clone() throws CloneNotSupportedException {Body newBody = (Body) super.clone();newBody.head = (Head) head.clone(); return newBody;}}
  相关解决方案