======================================================================================
首先一个对象的引用如果想要进行克隆,那么其对应的类必须实现Clonable 接口,并且重写Object类中的clone方法
,并且重写的clone方法后必须抛出CloneNotSupportedException 异常
.
我们直接通过代码来进行解析:先来看一段代码:
1.class Person implements Cloneable {
-
public int age;
-
@Override
-
//此处的clone方法必须抛出CloneNotSupportedException异常
-
protected Object clone() throws CloneNotSupportedException {
-
return super.clone();
-
}
8.}
9.//此处的主函数也需要抛出这个异常
-
public static void main(String[] args) throws CloneNotSupportedException {
-
Person person = new Person();
-
/*注意对于下面的调用clone方法有两点需要注意:
-
1:首先引用在调用clone方法时main方法需要抛出CloneNotSupportedException异常
-
2:因为clone方法的返回值为引用类型Object,所以如果是其他类定义的引用就需要强制类型转换
-
*/
-
Person person1 = (Person) person.clone();
-
System.out.println(person.age);
-
System.out.println(person1.age);
-
System.out.println("===========对比===========");
-
person1.age = 10;
-
System.out.println(person.age);
-
System.out.println(person1.age);
-
}
此段代码的输出结果为:
此时我们会发现首先我们对person所指向的对象进行了拷贝,并把它赋给了一个新的引用person1,那么此时在内存是什么样的呢?我们来看下图所示:
此时我们可以看到通过clone方法我们在堆上克隆了一个副本,并将这个副本对象赋给了一个新的引用,并且当我们修改person1这个引用所指向对象中所包含的简单类型age的值时,person这个引用所指向对象中所包含i的简单类型age的值并没有发生改变
,那么这种情况我们便称之为深拷贝
,即当拷贝结束后,通过一个新的引用修改所拷贝的新的对象的其中的某个类型的值时,并不影响原来引用所对应的相同对象中的相同类型的值,那么此时便为深拷贝
下面我们来介绍浅拷贝:
因为之前堆上的对象内部存储都是简单类型,所以都是深拷贝,那么如果存储引用类型后,就会发生浅拷贝了,下面来看代码:
1.class Money {
- double money = 12.6;
3.}
5.class Person implements Cloneable {
-
public int age;
-
Money m = new Money();
-
@Override
-
//此处的clone方法必须抛出CloneNotSupportedException异常
-
protected Object clone() throws CloneNotSupportedException {
-
return super.clone();
-
}
14.}
16.public class TestDemo {
-
public static void main(String[] args) throws CloneNotSupportedException {
-
Person person = new Person();
-
Person person1 = (Person) person.clone();
-
System.out.println(person.m.money);
-
System.out.println(person1.m.money);
-
System.out.println("===========对比===========");
-
person1.m.money = 99.9;
-
System.out.println(“修改后为”+person.m.money);
-
System.out.println(“修改后为”+person1.m.money);
-
}
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 {
- double money = 12.6;
总结:心得体会
既然选择这个行业,选择了做一个程序员,也就明白只有不断学习,积累实战经验才有资格往上走,拿高薪,为自己,为父母,为以后的家能有一定的经济保障。
学习时间都是自己挤出来的,短时间或许很难看到效果,一旦坚持下来了,必然会有所改变。不如好好想想自己为什么想进入这个行业,给自己内心一个答案。
面试大厂,最重要的就是夯实的基础,不然面试官随便一问你就凉了;其次会问一些技术原理,还会看你对知识掌握的广度,最重要的还是你的思路,这是面试官比较看重的。
最后,上面这些大厂面试真题都是非常好的学习资料,通过这些面试真题能够看看自己对技术知识掌握的大概情况,从而能够给自己定一个学习方向。包括上面分享到的学习指南,你都可以从学习指南里理顺学习路线,避免低效学习。
大厂Java架构核心笔记(适合中高级程序员阅读):
重要的还是你的思路,这是面试官比较看重的。
最后,上面这些大厂面试真题都是非常好的学习资料,通过这些面试真题能够看看自己对技术知识掌握的大概情况,从而能够给自己定一个学习方向。包括上面分享到的学习指南,你都可以从学习指南里理顺学习路线,避免低效学习。
大厂Java架构核心笔记(适合中高级程序员阅读):
[外链图片转存中…(img-YzRlBmlF-1714282564926)]