Clonable接口以及再次理解深拷贝与浅拷贝!!(面试常考)(1)

Clonable接口结合深拷贝问题与浅拷贝问题

======================================================================================

首先一个对象的引用如果想要进行克隆,那么其对应的类必须实现Clonable 接口,并且重写Object类中的clone方法,并且重写的clone方法后必须抛出CloneNotSupportedException 异常.

Clonable接口结合深拷贝


我们直接通过代码来进行解析:先来看一段代码:

1.class Person implements Cloneable {

  1. public int age;

  2. @Override

  3. //此处的clone方法必须抛出CloneNotSupportedException异常

  4. protected Object clone() throws CloneNotSupportedException {

  5.    return super.clone();  
    
  6. }

8.}

9.//此处的主函数也需要抛出这个异常

  1. public static void main(String[] args) throws CloneNotSupportedException {

  2.    Person person = new Person();  
    
  3.    /*注意对于下面的调用clone方法有两点需要注意: 
    
  4.    1:首先引用在调用clone方法时main方法需要抛出CloneNotSupportedException异常 
    
  5.    2:因为clone方法的返回值为引用类型Object,所以如果是其他类定义的引用就需要强制类型转换 
    
  6.     */  
    
  7.    Person person1 = (Person) person.clone();  
    
  8.    System.out.println(person.age);  
    
  9.    System.out.println(person1.age);  
    
  10.    System.out.println("===========对比===========");  
    
  11.    person1.age = 10;  
    
  12.    System.out.println(person.age);  
    
  13.    System.out.println(person1.age);  
    
  14. }

此段代码的输出结果为:

在这里插入图片描述

此时我们会发现首先我们对person所指向的对象进行了拷贝,并把它赋给了一个新的引用person1,那么此时在内存是什么样的呢?我们来看下图所示:

在这里插入图片描述

此时我们可以看到通过clone方法我们在堆上克隆了一个副本,并将这个副本对象赋给了一个新的引用,并且当我们修改person1这个引用所指向对象中所包含的简单类型age的值时,person这个引用所指向对象中所包含i的简单类型age的值并没有发生改变,那么这种情况我们便称之为深拷贝即当拷贝结束后,通过一个新的引用修改所拷贝的新的对象的其中的某个类型的值时,并不影响原来引用所对应的相同对象中的相同类型的值,那么此时便为深拷贝

Clonable接口结合浅拷贝


下面我们来介绍浅拷贝:

因为之前堆上的对象内部存储都是简单类型,所以都是深拷贝,那么如果存储引用类型后,就会发生浅拷贝了,下面来看代码:

1.class Money {

  1. double money = 12.6;

3.}

5.class Person implements Cloneable {

  1. public int age;

  2. Money m = new Money();

  3. @Override

  4. //此处的clone方法必须抛出CloneNotSupportedException异常

  5. protected Object clone() throws CloneNotSupportedException {

  6.    return super.clone();  
    
  7. }

14.}

16.public class TestDemo {

  1. public static void main(String[] args) throws CloneNotSupportedException {

  2.    Person person = new Person();  
    
  3.    Person person1 = (Person) person.clone();  
    
  4.    System.out.println(person.m.money);  
    
  5.    System.out.println(person1.m.money);  
    
  6.    System.out.println("===========对比===========");  
    
  7.    person1.m.money = 99.9;  
    
  8.    System.out.println(“修改后为”+person.m.money);  
    
  9.    System.out.println(“修改后为”+person1.m.money);  
    
  10. }

27.}

此时我们新建了一个Money类,并在Person类中加入了Money类的实例,那么此时Person类的实例在堆上的存储中便会多出一个引用类型,那么来看下其在内存上的存储示意图吧:

在这里插入图片描述

此时我们会发现我们通过clone方法仅仅将简单类型age和引用类型m克隆了过来但是m所指向的对象我们并没有克隆过来,那么两者的m引用都将会指向同一个对象

此时如果我们通过person1.m.money去修改money的值为99.9时我们会发现原引用person所对应的money值也随之变成了99.9,那么这种现象我们称之为浅拷贝即其当一个新的引用去修改其克隆过来的对象中的某个类型(此段代码为引用类型)的值后,原引用调用这个类型时便会发现这个值为新修改后的值了,并不是原来的值

所以上述代码中的最终结果我们会发现当其中一个引用修改了值后,另一个引用去调用时也会得到相同的值,我们来看运行结果以证实我们的猜想吧

在这里插入图片描述

果然就算修改过后两者的值依然相等

将深拷贝改为浅拷贝的方法

此时就会有同学有疑问了,上述代码如何可以实现深拷贝呢?

答案非常简单:此时我们让Money类实现Cloneable接口就好。目的就是为了将Money类的实例也能通过clone方法拷贝过来,下面来看代码:

1.class Money implements Cloneable {

  1. double money = 12.6;

总结:心得体会

既然选择这个行业,选择了做一个程序员,也就明白只有不断学习,积累实战经验才有资格往上走,拿高薪,为自己,为父母,为以后的家能有一定的经济保障。

学习时间都是自己挤出来的,短时间或许很难看到效果,一旦坚持下来了,必然会有所改变。不如好好想想自己为什么想进入这个行业,给自己内心一个答案。

面试大厂,最重要的就是夯实的基础,不然面试官随便一问你就凉了;其次会问一些技术原理,还会看你对知识掌握的广度,最重要的还是你的思路,这是面试官比较看重的。

最后,上面这些大厂面试真题都是非常好的学习资料,通过这些面试真题能够看看自己对技术知识掌握的大概情况,从而能够给自己定一个学习方向。包括上面分享到的学习指南,你都可以从学习指南里理顺学习路线,避免低效学习。

大厂Java架构核心笔记(适合中高级程序员阅读):

重要的还是你的思路,这是面试官比较看重的。

最后,上面这些大厂面试真题都是非常好的学习资料,通过这些面试真题能够看看自己对技术知识掌握的大概情况,从而能够给自己定一个学习方向。包括上面分享到的学习指南,你都可以从学习指南里理顺学习路线,避免低效学习。

大厂Java架构核心笔记(适合中高级程序员阅读):

[外链图片转存中…(img-YzRlBmlF-1714282564926)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值