Java中的浅复制和深复制 Cloneable clone
先看一个简单案例
public class Test {public static void main(String args[]) {Student stu1 = new Student();stu1.number = 1;Student stu2 = stu1;//stu1和stu2指向堆内存中同一个对象System.out.println("学生1:" + stu1.number + " 学生2:" + stu2.number);stu2.number = 2;System.out.println("学生1:" + stu1.number + " 学生2:" + stu2.number);System.out.println(stu1 == stu2);}}class Student {public int number;}如上这种形式,仅仅将一个对象的引用赋给另一个引用,并没有复制出另一个对象,这两个引用指向的是内存中的同一个对象所以,这根本不叫对象的复制
对象的复制(浅复制)
public class Test {public static void main(String args[]) {Student stu1 = new Student();stu1.number = 1;Student stu2 = (Student) stu1.clone();System.out.println("学生1:" + stu1.number + " 学生2:" + stu2.number);stu2.number = 2;System.out.println("学生1:" + stu1.number + " 学生2:" + stu2.number);System.out.println(stu1 == stu2);}}class Student implements Cloneable {public int number;@Overridepublic Object clone() {Student stu = null;try {stu = (Student) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return stu;}}Object有个protected的clone方法,该方法的签名是:protected native Object clone() throws CloneNotSupportedException;要想对一个对象进行复制,就需要覆盖clone方法,一般步骤是(浅复制):
- 1、被复制的类需要实现Clonenable接口,不实现的话在调用clone方法会抛出CloneNotSupportedException异常,该接口为标记接口(不含任何方法)
- 2、覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象(native为本地方法)
浅复制可能出现的问题
public class Test {public static void main(String args[]) {Student stu1 = new Student();stu1.number = 1;stu1.address = new Address("广州");stu1.courseList.add("语文");//复制stu1Student stu2 = (Student) stu1.clone();System.out.println("学生1:" + stu1.number + " " + stu1.address + " " + stu1.courseList);System.out.println("学生2:" + stu2.number + " " + stu2.address + " " + stu2.courseList);//更改stu2stu2.number = 2;stu2.address = new Address("深圳");stu2.courseList.add("数学");System.out.println("学生1:" + stu1.number + " " + stu1.address + " " + stu1.courseList);System.out.println("学生2:" + stu2.number + " " + stu2.address + " " + stu2.courseList);}}class Student implements Cloneable {public int number;public ArrayList<String> courseList = new ArrayList<String>();public Address address;@Overridepublic Object clone() {Student stu = null;try {stu = (Student) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return stu;}}class Address {public String add;public Address(String add) {this.add = add;}}更改stu2的address和courseList后,是不是发现,stu1的相应值也变了?这是为什么呢?这是因为Java做了一个偷懒的拷贝动作,Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素的地址,这种拷贝就叫做浅拷贝。确实是非常浅,两个对象共享了一个私有变量,你改我改大家都能改,是一个种非常不安全的方式,在实际项目中使用还是比较少的。注意:八大基本类型和String(虽然String 是引用类型,但Java其实是希望你把它也"认为"是基本类型,String 是没有 clone 方法的)等都会被拷贝的。
深复制
public class Test {public static void main(String args[]) {Student stu1 = new Student();stu1.number = 1;stu1.address = new Address("广州");stu1.courseList.add("语文");//复制stu1Student stu2 = (Student) stu1.clone();System.out.println("学生1:" + stu1.number + " " + stu1.address + " " + stu1.courseList);System.out.println("学生2:" + stu2.number + " " + stu2.address + " " + stu2.courseList);//更改stu2stu2.number = 2;stu2.address = new Address("深圳");stu2.courseList.add("数学");System.out.println("学生1:" + stu1.number + " " + stu1.address + " " + stu1.courseList);System.out.println("学生2:" + stu2.number + " " + stu2.address + " " + stu2.courseList);}}class Student implements Cloneable {public int number;public ArrayList<String> courseList = new ArrayList<String>();public Address address;@SuppressWarnings("unchecked")@Overridepublic Object clone() {Student stu = null;try {stu = (Student) super.clone();//浅复制stu.address = (Address) address.clone(); //深度复制stu.courseList = (ArrayList<String>) courseList.clone();//深度复制} catch (CloneNotSupportedException e) {e.printStackTrace();}return stu;}}class Address implements Cloneable {//为了达到真正的复制对象,而不是纯粹引用复制。我们需要将Address类可复制化public String add;public Address(String add) {this.add = add;}@Overridepublic Object clone() {Address addr = null;try {addr = (Address) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return addr;}}
Java中的浅复制和深复制 Cloneable clone的更多相关文章
- JAVA中浅复制与深复制 - coolmist - ITeye技术网站
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- Java中引用的浅复制和深复制
Java中除了基本类型int,char,double等的赋值是按照值传递之外,其余的类型和对象都是按照引用进行传递的. 下面来看一个关于引用的例子. package referenceCopy;// ...
- JAVA中浅复制与深复制
1.浅复制与深复制概念⑴浅复制(浅克隆)被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵深复 ...
- Java中的“浅复制”与“深复制”
复制 将一个对象的引用复制给另一个对象,一共有三种方式.第一种方式是直接赋值,第二种方式是浅复制,第三种方式是深复制. 1.直接赋值 在Java中,A a1 = a2,这实际上复制的是引用,也就是说 ...
- java基础-浅复制与深复制的理解
浅复制与深复制在很多编程语言中都有出现,那么什么是浅复制,什么是深复制呢? 要区分浅复制与深复制,首先我们要明确什么是复制,怎样才算是复制.复制的例子在生活中也随处可见,如复印一份文档,复制一段文字等 ...
- Java里的浅复制与深复制
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不 复制它所引用的对象. ...
- 深度解析javascript中的浅复制和深复制
原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null ...
- js中的浅复制和深复制
浅复制:浅复制是复制引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响 深复制:深复制不是简单的复制引用,而是在堆中重新分配内存,并且把源对象实例的所有属性都进行新建复制,以保证深复 ...
- Python中的浅复制、深复制
参考 https://docs.python.org/3/library/copy.html?highlight=copy%20copy#copy.copy https://en.wikipedia. ...
- php对象复制、clone、浅复制与深复制实例详解
php对象复制.clone.浅复制与深复制实例详解 一.用clone(克隆)来复制对象$obj1 = new Object();$obj2 = clone $obj1;clone方法会触发对象里定义的 ...
随机推荐
- python自动开发之第二十一天
一.请求周期 url> 路由 > 函数或类 > 返回字符串或者模板语言? 1.Form表单提交: 提交 -> url > 函数或类中的方法 - .... HttpResp ...
- 利用HTML5分片上传超大文件
在网页中直接上传大文件一直是个比较头疼的问题,主要面临的问题一般包括两类:一是上传时间长中途一旦出错会导致前功尽弃:二是服务端配置复杂,要考虑接收超大表单和超时问题,如果是托管主机没准还改不了配置,默 ...
- Popular Deep Learning Tools – a review
Popular Deep Learning Tools – a review Deep Learning is the hottest trend now in AI and Machine Lear ...
- vss报错Workgroup无法访问,您可能没有权限使用网络资源解决办法
xp下访问svn或者vss的时候只能使用ip进行访问表示很不爽,昨天还好好的,结果就不能使用计算机名字去访问了. 很是郁闷,打开网上邻居之后发现,居然连网上邻居都搜不出来,于是关掉windows自带防 ...
- java interface
- 线段树(维护最大值):HDU Billboard
Billboard Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 【有源汇上下界费用流】BZOJ 3876 [Ahoi2014]支线剧情
题目链接: http://www.lydsy.com:808/JudgeOnline/problem.php?id=3876 题目大意: 给定一张拓扑图(有向无环图),每条边有边权,每次只能从第一个点 ...
- ASP.NET网站发布-允许更新此预编译站点 打勾与不打勾的区别
发布网站时在打开的对话框中,有一个选项是至关重要的,那就是“允许更新此预编译站点”: “允许更新此预编译站点”这一项,默认情况下,前面是打上一个√的,至于要不要打上一个√,是可选的,那么,打勾与不打勾 ...
- [Locked] 3Sum Smaller
3Sum Smaller Given an array of n integers nums and a target, find the number of index triplets i, j, ...
- lightoj 1198 最大权重匹配
题目链接:http://lightoj.com/volume_showproblem.php?problem=1198 #include <cstdio> #include <cst ...