面试官:深拷贝与浅拷贝有啥区别? 您所在的位置:网站首页 java中复制文件的方法 面试官:深拷贝与浅拷贝有啥区别?

面试官:深拷贝与浅拷贝有啥区别?

2023-06-11 22:53| 来源: 网络整理| 查看: 265

文章目录 1.前言2.基本类型的拷贝3.引用类型的拷贝3.1 关于引用类型的浅拷贝3.2 关于引用类型的深拷贝

1.前言

首先,明确一点深拷贝和浅拷贝是针对对象属性为对象的,因为基本数据类型在进行赋值操作时(也就是拷贝)是直接将值赋给了新的变量,也就是该变量是原变量的一个副本,这个时候你修改两者中的任何一个的值都不会影响另一个,而对象或者引用数据来说在进行浅拷贝时,只是将对象的引用复制了一份,也就内存地址;即两个不同的变量指向了同一个内存地址,那么在改变任一个变量的值都是改变这个内存地址所指向的值,所以两个变量的值都会改变。 上方这句话不太好理解,这样,我把他们区别出来,做两个讲解,一个是关于基本类型的拷贝;一个关于引用数据类型的拷贝,分开理解,会大大降低学习成本~

2.基本类型的拷贝

在基本类型的拷贝中,深拷贝和浅拷贝的作用就没什么区别了,拷贝出来的对象都是拥有相同的数值,这里用语言文字很难描述,可以看下面的代码和图来帮助理解。

public static void main(String[] args) throws CloneNotSupportedException { //原来的对象 Person person1=new Person("张三",15); //克隆出来的对象 Person person2=(Person) person1.clone(); }

我们打印这两个对象的地址: 观察可以看出,他两个的地址是不相同的,也就是说,他两个现在是不同的对象。 在这里插入图片描述 他两个在堆、栈图中是如何表示的呢?看下方的图: 我们可以看出,p2把p1中的所有数据都重新生成了一份,让给让p2指向新生成的那份数据。 在这里插入图片描述

3.引用类型的拷贝

这个就很有引用类型拷贝就会在深拷贝和浅拷贝上区别很大了! 我们仍然以人来举例子,人身上一般都会带着money,我们给人添加一个新的成员变量(钱),并且我们让钱这个成员变量改为引用变量。

3.1 关于引用类型的浅拷贝 class Money { public double value=99.99; } class Person implements Cloneable{ public String name; public int age; public Money money=new Money(); public Person(String name, int age) { this.name = name; this.age = age; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } public class testDemo2 { public static void main(String[] args) throws CloneNotSupportedException { //原来的对象 Person person1=new Person("张三",15); //克隆出来的对象 Person person2=(Person) person1.clone(); System.out.print("p1的钱钱数:"); System.out.println(person1.money.value); System.out.print("p2的钱钱数:"); System.out.println(person2.money.value); } }

打印出来的结果:

p1的钱钱数:99.99 p2的钱钱数:99.99

我们可以观察结果得出,p1的钱钱和p2的钱钱我们设置好的99.99。 当我们去尝试修改p1钱钱的数时:

public static void main(String[] args) throws CloneNotSupportedException { //原来的对象 Person person1=new Person("张三",15); //克隆出来的对象 Person person2=(Person) person1.clone(); System.out.println("修改p1的钱钱数"); person1.money.value=50; System.out.print("p1的钱钱数:"); System.out.println(person1.money.value); System.out.print("p2的钱钱数:"); System.out.println(person2.money.value); }

代码打印结果: 在这里插入图片描述 我去,你修改p1的钱钱数,为啥我p2的钱钱数也发送了改变,这不就相当于别人花的钱扣在了我身上?这可不是我想要的结果! 这到底怎能回事?其实很好理解,当我们在进行拷贝时,我们拷贝money这个成员变量时,我们拷贝的数值是一个引用变量,这个引用变量又指向一个对象。因此当我们修改p1的钱的数值时,我们时顺着引用变量找所指向的值将其修改了,又因为两个引用对象指向同一个值,因此修改后,再通过引用变量查看值,就是修改后的值了;上述过程就是浅拷贝了,它的结构图如下: 在这里插入图片描述

3.2 关于引用类型的深拷贝

如何解决这样的问题呢?其实很简单,当我们进行拷贝时,我们让引用变量引用的对象重新创建一个新的对象,并且让拷贝的那一份的引用变量指向创建的对象。 我们主要修改的就算Person类中的clone方法,我们先让Money类实现Cloneable接口,然后在Person类中的clone方法调用Money类中的clone方法。(这里比较绕,看不懂没关系,下面有画的结构图,图看起来会很好理解!)

class Money implements Cloneable{ public double value=99.99; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Person implements Cloneable{ public String name; public int age; public Money money=new Money(); public Person(String name, int age) { this.name = name; this.age = age; } @Override protected Object clone() throws CloneNotSupportedException { Person person=(Person) super.clone(); person.money=(Money) person.money.clone(); return person; } } public class testDemo2 { public static void main(String[] args) throws CloneNotSupportedException { //原来的对象 Person person1=new Person("张三",15); //克隆出来的对象 Person person2=(Person) person1.clone(); System.out.println("修改p1的钱钱数"); person1.money.value=50; System.out.print("p1的钱钱数:"); System.out.println(person1.money.value); System.out.print("p2的钱钱数:"); System.out.println(person2.money.value); } }

代码运行出来的结果: 可以看出,修改p1的钱数,不在应用p2的钱数了。 在这里插入图片描述 上方这个过程就是深拷贝,深拷贝的结构图如下: 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有