先看一个简单案例

  1. public class Test {
  2.     public static void main(String args[]) {
  3.         Student stu1 = new Student();
  4.         stu1.number = 1;
  5.         Student stu2 = stu1;//stu1和stu2指向堆内存中同一个对象
  6.         System.out.println("学生1:" + stu1.number + "    学生2:" + stu2.number);
  7.         stu2.number = 2;
  8.         System.out.println("学生1:" + stu1.number + "    学生2:" + stu2.number);
  9.         System.out.println(stu1 == stu2);
  10.     }
  11. }
  12. class Student {
  13.     public int number;
  14. }

  15. 如上这种形式,仅仅将一个对象的引用赋给另一个引用,并没有复制出另一个对象,这两个引用指向的是内存中的同一个对象
  16. 所以,这根本不叫对象的复制
  17.  

对象的复制(浅复制)

  1. public class Test {
  2.     public static void main(String args[]) {
  3.         Student stu1 = new Student();
  4.         stu1.number = 1;
  5.         Student stu2 = (Student) stu1.clone();
  6.         System.out.println("学生1:" + stu1.number + "    学生2:" + stu2.number);
  7.         stu2.number = 2;
  8.         System.out.println("学生1:" + stu1.number + "    学生2:" + stu2.number);
  9.         System.out.println(stu1 == stu2);
  10.     }
  11. }
  12. class Student implements Cloneable {
  13.     public int number;
  14.     @Override
  15.     public Object clone() {
  16.         Student stu = null;
  17.         try {
  18.             stu = (Student) super.clone();
  19.         } catch (CloneNotSupportedException e) {
  20.             e.printStackTrace();
  21.         }
  22.         return stu;
  23.     }
  24. }

  25. Object有个protectedclone方法,该方法的签名是:
  26. protected native Object clone() throws CloneNotSupportedException;
  27. 要想对一个对象进行复制,就需要覆盖clone方法,一般步骤是(浅复制):
    • 1、被复制的类需要实现Clonenable接口,不实现的话在调用clone方法会抛出CloneNotSupportedException异常,该接口为标记接口(不含任何方法)
    • 2、覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象(native为本地方法)
  28.  

浅复制可能出现的问题

  1. public class Test {
  2.     public static void main(String args[]) {
  3.         Student stu1 = new Student();
  4.         stu1.number = 1;
  5.         stu1.address = new Address("广州");
  6.         stu1.courseList.add("语文");

  7.         //复制stu1
  8.         Student stu2 = (Student) stu1.clone();
  9.         System.out.println("学生1:" + stu1.number + "    " + stu1.address + "    " + stu1.courseList);
  10.         System.out.println("学生2:" + stu2.number + "    " + stu2.address + "    " + stu2.courseList);

  11.         //更改stu2
  12.         stu2.number = 2;
  13.         stu2.address = new Address("深圳");
  14.         stu2.courseList.add("数学");
  15.         System.out.println("学生1:" + stu1.number + "    " + stu1.address + "    " + stu1.courseList);
  16.         System.out.println("学生2:" + stu2.number + "    " + stu2.address + "    " + stu2.courseList);
  17.     }
  18. }
  19. class Student implements Cloneable {
  20.     public int number;
  21.     public ArrayList<String> courseList = new ArrayList<String>();
  22.     public Address address;
  23.     @Override
  24.     public Object clone() {
  25.         Student stu = null;
  26.         try {
  27.             stu = (Student) super.clone();
  28.         } catch (CloneNotSupportedException e) {
  29.             e.printStackTrace();
  30.         }
  31.         return stu;
  32.     }
  33. }
  34. class Address {
  35.     public String add;
  36.     public Address(String add) {
  37.         this.add = add;
  38.     }
  39. }

  40. 更改stu2addresscourseList后,是不是发现,stu1的相应值也变了?这是为什么呢?
  41. 这是因为Java做了一个偷懒的拷贝动作,Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素的地址,这种拷贝就叫做浅拷贝。
  42. 确实是非常浅,两个对象共享了一个私有变量,你改我改大家都能改,是一个种非常不安全的方式,在实际项目中使用还是比较少的。
  43. 注意:八大基本类型和String(虽然String 是引用类型,但Java其实是希望你把它也"认为"是基本类型,String 是没有 clone 方法的)等都会被拷贝的。
  44.  

深复制

  1. public class Test {
  2.     public static void main(String args[]) {
  3.         Student stu1 = new Student();
  4.         stu1.number = 1;
  5.         stu1.address = new Address("广州");
  6.         stu1.courseList.add("语文");
  7.         //复制stu1
  8.         Student stu2 = (Student) stu1.clone();
  9.         System.out.println("学生1:" + stu1.number + "    " + stu1.address + "    " + stu1.courseList);
  10.         System.out.println("学生2:" + stu2.number + "    " + stu2.address + "    " + stu2.courseList);
  11.         //更改stu2
  12.         stu2.number = 2;
  13.         stu2.address = new Address("深圳");
  14.         stu2.courseList.add("数学");
  15.         System.out.println("学生1:" + stu1.number + "    " + stu1.address + "    " + stu1.courseList);
  16.         System.out.println("学生2:" + stu2.number + "    " + stu2.address + "    " + stu2.courseList);
  17.     }
  18. }
  19. class Student implements Cloneable {
  20.     public int number;
  21.     public ArrayList<String> courseList = new ArrayList<String>();
  22.     public Address address;
  23.     @SuppressWarnings("unchecked")
  24.     @Override
  25.     public Object clone() {
  26.         Student stu = null;
  27.         try {
  28.             stu = (Student) super.clone();//浅复制 
  29.             stu.address = (Address) address.clone(); //深度复制
  30.             stu.courseList = (ArrayList<String>) courseList.clone();//深度复制
  31.         } catch (CloneNotSupportedException e) {
  32.             e.printStackTrace();
  33.         }
  34.         return stu;
  35.     }
  36. }
  37. class Address implements Cloneable {//为了达到真正的复制对象,而不是纯粹引用复制。我们需要将Address类可复制化
  38.     public String add;
  39.     public Address(String add) {
  40.         this.add = add;
  41.     }
  42.     @Override
  43.     public Object clone() {
  44.         Address addr = null;
  45.         try {
  46.             addr = (Address) super.clone();
  47.         } catch (CloneNotSupportedException e) {
  48.             e.printStackTrace();
  49.         }
  50.         return addr;
  51.     }
  52. }

  53.  

Java中的浅复制和深复制 Cloneable clone的更多相关文章

  1. JAVA中浅复制与深复制 - coolmist - ITeye技术网站

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  2. Java中引用的浅复制和深复制

    Java中除了基本类型int,char,double等的赋值是按照值传递之外,其余的类型和对象都是按照引用进行传递的. 下面来看一个关于引用的例子. package referenceCopy;// ...

  3. JAVA中浅复制与深复制

    1.浅复制与深复制概念⑴浅复制(浅克隆)被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵深复 ...

  4. Java中的“浅复制”与“深复制”

    复制 将一个对象的引用复制给另一个对象,一共有三种方式.第一种方式是直接赋值,第二种方式是浅复制,第三种方式是深复制. 1.直接赋值 在Java中,A a1 = a2,这实际上复制的是引用,也就是说 ...

  5. java基础-浅复制与深复制的理解

    浅复制与深复制在很多编程语言中都有出现,那么什么是浅复制,什么是深复制呢? 要区分浅复制与深复制,首先我们要明确什么是复制,怎样才算是复制.复制的例子在生活中也随处可见,如复印一份文档,复制一段文字等 ...

  6. Java里的浅复制与深复制

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不 复制它所引用的对象. ...

  7. 深度解析javascript中的浅复制和深复制

    原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null ...

  8. js中的浅复制和深复制

    浅复制:浅复制是复制引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响 深复制:深复制不是简单的复制引用,而是在堆中重新分配内存,并且把源对象实例的所有属性都进行新建复制,以保证深复 ...

  9. Python中的浅复制、深复制

    参考 https://docs.python.org/3/library/copy.html?highlight=copy%20copy#copy.copy https://en.wikipedia. ...

  10. php对象复制、clone、浅复制与深复制实例详解

    php对象复制.clone.浅复制与深复制实例详解 一.用clone(克隆)来复制对象$obj1 = new Object();$obj2 = clone $obj1;clone方法会触发对象里定义的 ...

随机推荐

  1. Python入门,新手之路

    1.开始使用Python: 从上一篇中我们提到了第一个Python,print("Hello World!")程序说起,看到这一句话,你有没有想过如果括号中的语句不是Hello W ...

  2. 老oj曼哈顿最小生成树

    Description 平面坐标系xOy内,给定n个顶点V = (x , y).对于顶点u.v,u与v之间的距离d定义为|xu – xv| + |yu – yv| 你的任务就是求出这n个顶点的最小生成 ...

  3. iOS9 未受信任的企业级开发者

    升级iOS9,app打不开怎么办?6个步骤让你应对“未受信任的企业及开发者账号” 点开App,弹出未受信任的开发者,记住弹框中冒号后面的大写字母.关闭,进入设置. 进入通用 进入描述文件 找到所对应的 ...

  4. 酷炫地给py代码标上行数

    Python IDLE是没有显示行号的功能的,今天学了一个方式可以酷炫地给自己的代码加上行号,该方法直接修改代码,慎用哦!代码如下: import fileinput for line in file ...

  5. Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二)

    Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二) 题记:  前文<Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一)>中提 ...

  6. oracle 的一点累积

    1.  oracle用户相关 sqlplus sys/oracle as sysdba    -- sys登录 create user xxx identified by password;   -- ...

  7. HDOJ迷宫城堡(判断强连通 tarjan算法)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...

  8. POJ-3468-A Simple Problem with Integers(区间更新,求和)-splay或线段树

    区间更新求和 主要用来练习splay树区间更新问题 //splay树的题解 // File Name: 3468-splay.cpp // Author: Zlbing // Created Time ...

  9. IOI 2009:Mecho

    IOI2009 Mecho Time Limit: 10000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Origin ...

  10. Selenium自动化测试环境搭建汇总(一):Selenium+Eclipse+Junit+TestNG

    第一步 安装JDK JDk1.7. 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-188026 ...