Cloneable接口以及深拷贝和浅拷贝
目录
1.Cloneable接口
1.1Cloneable接口中什么方法都没有,那为什么要继承该接口?
1.2.Cloneable接口什么方法都没有,那我该重写谁的clone()方法来实现对象拷贝?
1.3.实现对象拷贝的方法步骤
1.3.1让Person类实现Cloneadble接口
1.3.2重写Object的clone()方法
1.3.3注意抛异常和和向下转型
1.4.代码实现
2.深拷贝
3.浅拷贝
如何发生浅拷贝?
将浅拷贝变成深拷贝的思路
1.Cloneable接口
1.1Cloneable接口中什么方法都没有,那为什么要继承该接口?
解答:在Cloneable接口的源码中,里面什么方法都没有,但是implements该接口的类则证明该类是可以被克隆的。
Cloneable接口源码
1.2.Cloneable接口什么方法都没有,那我该重写谁的clone()方法来实现对象拷贝?
解答:所有类都默认继承Object类,所以需要重写Object类中的clone()方法就能实现对象的拷贝了。
1.3.实现对象拷贝的方法步骤
我以自定义Person类举例
1.3.1让Person类实现Cloneadble接口
1.3.2重写Object的clone()方法
1.3.3注意抛异常和和向下转型
1.4.代码实现
class Person implements Cloneable{public int age;public int id;public Person(int age, int id) {this.age = age;this.id = id;}@Overridepublic String toString() {return "Person{" +"age=" + age +", id=" + id +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class CloneableDemo {public static void main(String[] args) throws CloneNotSupportedException{Person person1 = new Person(10,0001);//1.由于重写的clone方法会抛出编译时异常,要么try-catch,要么继续抛//2.clone()方法返回值为Object类型,因此需要向下转型Person person2 = (Person)person1.clone();System.out.println(person1);System.out.println(person2);}
}
结果:
图解代码:
2.深拷贝
简单理解:我改变person1对象中的属性值,不会影响到person2对象中的属性值,那么就叫做深拷贝。
从上图中可知,如果我修改person1对象的age属性为200,id属性也为200,应该是不会影响person2对象的属性值的。
直接看代码:
结果:可以发现,改变了person1对象中的成员变量的值,并不会影响person2中成员变量的值。
3.浅拷贝
简单理解:我改变person1对象中的属性值,会影响到person2对象中的属性值,那么就叫做深拷贝。
看到这块基本上也就理解了Cloneable接口、深浅拷贝了。
接下来会说一说,如何发生浅拷贝,以及如何将浅拷贝转化为深拷贝。
---------------------------------------------------------------------------------------------------------------------------------
如何发生浅拷贝?
如下图所示,如果给我的Person类当中再添加一个引用类型的成员变量 ,那此时在调用clone()方法时,拷贝的副本(person2所指的对象)会将原对象当中的所有值全部拷贝,此时副本中的引用类型变量也存储的是0x999的地址,那么也就会让副本中的引用类型变量和原对象的引用类型变量指向同一片空间。如果指向了同一片空间,修改person1对象中引用类型的变量值就会让person2的变量值也会发生改变,那是不是就发生了浅拷贝!!!
代码演示:再自定义一个Money类,在Person类中定义一个Money类型的变量。
给person1.money.salary = 12,person2.money.salary = 200
结果:结果最终都是200,这次是浅拷贝了,但我们希望他们两个对象互不影响(也就是深拷贝)
将浅拷贝变成深拷贝的思路
方法一:
1.我们可以先将引用类型(Money)所指向的对象拷贝一份
2.接着我们在拷贝Person类的对象
3.让Person类对象的引用变量指向最初拷贝的那个(Money)对象
画个图解释一下
核心代码的实现:
结果:
源代码:
class Money implements Cloneable{public int salary;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
class Person implements Cloneable{public int age;public int id;public Money money = new Money();public Person(int age, int id) {this.age = age;this.id = id;}@Overridepublic String toString() {return "Person{" +"age=" + age +", id=" + id +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class CloneableDemo {public static void main(String[] args) throws CloneNotSupportedException{Person person1 = new Person(10,0001);person1.money.salary = 12;//1.先拷贝money对象Money temp = (Money)person1.money.clone();//2.在拷贝person2对象Person person2 = (Person)person1.clone();//3.person2.money指向tempperson2.money = temp;person2.money.salary = 200;System.out.println(person1.money.salary);System.out.println(person2.money.salary);}
}
方法二:
方法一是在main方法中进行修改的,我们希望调用完clone()方法就能做到深拷贝,因此需要修改Person类中的clone方法
图解:
核心代码块:
结果:两者已经互不影响了
源代码:
class Money implements Cloneable{public int salary;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
class Person implements Cloneable{public int age;public int id;public Money money = new Money();public Person(int age, int id) {this.age = age;this.id = id;}@Overridepublic String toString() {return "Person{" +"age=" + age +", id=" + id +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {//先克隆一个Person对象副本Person personTemp = (Person)super.clone();//2.在克隆money对象的副本,并将副本的money指向克隆出来的money对象personTemp.money = (Money)this.money.clone();//3.返回该Person类对象的引用return personTemp;}
}
public class CloneableDemo {public static void main(String[] args) throws CloneNotSupportedException{Person person1 = new Person(10,0001);person1.money.salary = 12;Person person2 = (Person)person1.clone();person2.money.salary = 200;System.out.println(person1.money.salary);System.out.println(person2.money.salary);}
}
Cloneable接口以及深拷贝和浅拷贝相关推荐
- 【Java】Cloneable 接口讲解 (包含浅拷贝与深拷贝不一样的实现讲解)
在Java中除了new关键字可以创建对象(实例化对象)以外,使用Cloneable接口也可以实现对象的创建,具体用法如下: Cloneable接口比较特殊,虽然他是一个口接口,但是我们也必须重写clo ...
- 【Java】深拷贝和浅拷贝,Cloneable接口
活动地址:CSDN21天学习挑战赛 ✨博客主页: XIN-XIANG荣 ✨系列专栏:[Java SE] ✨一句短话: 难在坚持,贵在坚持,成在坚持! 文章目录 1. Cloneable接口的介绍 2. ...
- 谈一谈Java中的深拷贝和浅拷贝
在 Java 开发中,对象拷贝或者说对象克隆是常有的事,对象克隆最终都离不开直接赋值.浅拷贝.深拷贝 这三种方式,其中直接赋值应该是我们最常用的一种方式吧,对于浅拷贝和深拷贝可能用的少,所以或多或少存 ...
- Comparable接口、Comparator接口、Cloneable接口
Comparable接口与比较器Comparator接口 Comparable接口用来比较两个对象属性的大小,实现Comparable接口需要重写compareTo抽象方法,通过重写并调用compar ...
- Java 中的接口以及常见的 Cloneable 接口
目录 1. 概念 2. 语法规则 3. 接口的命名规则 4. 实现多个接口 5. 接口实现示例 6. Cloneable 接口和深.浅拷贝 6.1 Cloneable 接口 6.2 浅拷贝 6.3 深 ...
- clone是深拷贝还是浅拷贝_Cloneable接口的作用与探索理解浅拷贝与深拷贝
导读:本文将主要讨论设计模式--原型模式中,关于cloneable接口及浅拷贝与深拷贝的概念. 原型模式的理解 关于原型模式的理解,我在网上发现一个有趣且助于理解原型模式的例子在这里分享一下:火影忍者 ...
- 【Java基础系列教程】第八章 Java面向对象详解(三)_抽象类、接口、内部类、深拷贝与浅拷贝
一.JavaBean规范 1.1 什么是JavaBean JavaBeans是Java中一种特殊的类,可以将多个对象封装到一个对象(bean)中.特点是可序列化,提供无参构造器,提供getter方法和 ...
- 1.19(对象类型判断、复制、in、遍历;深拷贝与浅拷贝;字符串的遍历接口、模板字符串、字符串扩展方法)
1.19(对象类型判断.复制.in.遍历;深浅拷贝;字符串的遍历接口.模板字符串.unicode.字符串扩展方法) 一.对象 1.属性简洁表示法与属性名表达式 let name = "wuy ...
- Java深拷贝与浅拷贝
前言 对象拷贝Object Copy是将一个对象的属性,拷贝到另一个相同类型的对象中.拷贝对象主要是为了在新的上下文环境中复用对象的部分或全部数据.其中对象拷贝有3种类型:深拷贝Deep Copy.浅 ...
最新文章
- 用 Python 制作数据大屏,超简单
- Pycharm常用的使用方法
- PHP 函数dirname()使用实例
- Silverlight与HTML双向交互
- Spring MVC:会话高级
- python怎么放音乐_python怎么播放音乐
- 哪里的mysql性能监控_mysql性能监控工具Innotop简介及配置
- 人在斯坦福,刚上CS224n
- 初学Java学员,千万不要踩这几个坑
- 莫烦python简历_Matplotlib画图教程
- 社交媒体电影视频网HTML5模板
- ASP.NET中获取URL重写前的原始地址
- java vector实现的接口_java的List接口的实现类 ArrayList,LinkedList,Vector 的区别
- prinect pdf toolbox 2021中文版
- latex tabular 单元格里换行
- 推荐4个爬虫抓包神器
- format mla_MLAFormatMLA格式解读
- 使用matlab编写协方差矩阵计算矩阵
- 使命召唤9怎么样使用计算机,玩家实测COD9 教你如何使用FXAA、TXAA
- FCN训练自己数据集(person-segmentation)、SIFT-FLOW、SBD和VOC实验总结