一.深拷贝和浅拷贝的概念
浅拷贝(Shallow Copy):创建一个新对象,新对象的基本数据类型成员的值会被复制,而引用数据类型成员仍然指向原始对象所指向的内存地址。也就是说,浅拷贝只是复制了对象的“顶层”,对于引用类型的成员,实际上复制的是引用,而不是引用所指向的对象。
深拷贝(Deep Copy):创建一个新对象,不仅复制基本数据类型成员的值,对于引用数据类型的成员,也会为其创建新的对象,并复制其内容,使得新对象和原始对象完全独立,修改其中一个对象的引用类型成员不会影响到另一个对象。
二.使用拷贝的步骤
第一步:类要先实现Cloneable接口。
第二步:重写clone方法。
这是Java自带的克隆方法。
为什么要重写clone方法呢?
不重写就报错了,因为clone
方法在 java.lang.Object
类中是 protected
访问权限的。这意味着直接在自定义类中调用 clone
方法是不被允许的,除非在自定义类中重写 clone
方法并将其访问权限扩大为 public
或者其他更宽松的访问级别。
clone
方法声明抛出 CloneNotSupportedException
异常的原因?
1. 并非所有类都适合或支持克隆操作:有些类的内部结构或依赖关系可能使得简单的克隆操作无法实现或者不恰当。通过抛出这个异常,可以明确告知调用者该类可能不支持克隆,或者在当前环境中克隆操作无法完成。
2.处理潜在的克隆错误:在克隆过程中,可能会出现各种无法预料的问题,例如对象内部包含无法克隆的资源、对象的状态不适合克隆等。通过抛出异常,可以将这些错误情况传递给调用者,让调用者决定如何处理。
3.遵循 Java 的异常处理原则:对于可能出现异常的操作,按照良好的编程实践,应当声明可能抛出的异常,以便调用者能够进行适当的异常处理,增强程序的健壮性和可靠性。
这样就重写了clone方法。
第三步:向下转型和声明CloneNotSupportedException
异常。 为什么要向下转型呢?
因为你的test1.clone()表示的是object对象,而你提供的是test对象,object类是所有类的父类,所以需要向下转型。
为什么函数要声明CloneNotSupportedException
异常呢?
因为CloneNotSupportedException
异常是编译时的异常,是在运行前都需要处理的,clone方法声明了CloneNotSupportedException异常,是指可能会出现的异常,所以函数也需要声明。
三.深拷贝和浅拷贝的区别
1.浅拷贝
把test1克隆给test2,如图所示,false证明了两者不是同一个对象,而是又创建出了一个新对象。
test2改变值,test1的值不变。
可以这样理解。
但是,如下图:
发现money的值改变了。
我用下图帮你们理解一下
只是拷贝了Person并没有拷贝money对象,所以他俩的money对象都是指向同一块地址的内容,当然会发生改变,只是浅拷贝的缺点。
2.深拷贝
目标:实现money的独立,就是改变一个person.money.m的值,另一个不变。
简单来说,这就是深拷贝。
接下来我来完成,我们首先需要的就是让money类也实现Cloneable接口。
接下来修改person类中的clone方法。
我来结合下图解释一下。
这是借用别人的图片,这里的m也就是咱的实例化money对象。
深拷贝技术先是克隆出来一个person对象,然后,又克隆出来了一个money对象,最后把tmp对象返回给person1,此时person1和person都有自己的money对象,相互不会影响。
四.结束语
感谢大家的查看,希望可以帮助到大家,做的不是太好还请见谅,其中有什么不懂的可以留言询问,我都会一一回答。 感谢大家的一键三连。