`

深入对象复制与比较

    博客分类:
  • java
J# 
阅读更多

1.对象的复制
2.clone()的使用
3.对象实例的比较
////////////////////
//
/////////////////////

1.对象的复制

 

  1.    
  2. String str1 = "This is a string!"  //这里是 "对象引用" 的复制
  3. String str2 = new String(str1);  //这里是 "对象实例" 的复制


浅复制: 只复制复合对象本身.
深复制: 除了复制复合对象本身, 还复制了复合对象的引用的对象实例.

例如:

  1. class Pupil{
  2.     public Pupil(String sno, String name, int age){
  3.         this.sno = new String(sno);
  4.         this.name = new String(name);
  5.         this.age = age;
  6.     }
  7.     public String getSno() {
  8.         return sno;
  9.     }
  10.     public String getName() {
  11.         return name;
  12.     }
  13.     public int getAge() {
  14.         return age;
  15.     }
  16.     public void setAge(int age) {
  17.         this.age = age;
  18.     }
  19.     private String sno;
  20.     private String name;
  21.     private int age;
  22. }
  23. public class CopyDemo {
  24.     public static Pupil[] shallowCopy(Pupil[] aClass) {
  25.         Pupil[] newClass = new Pupil[aClass.length];
  26.         //此时newClass 与aClass 指向同一块内存
  27.         for(int i=0; i<aClass.length; i++)
  28.             newClass[i] = aClass[i];
  29.         return newClass;
  30.     }
  31.     
  32.     public static Pupil[] deepCopy(Pupil[] aClass) {
  33.         Pupil[] newClass = new Pupil[aClass.length];
  34.         //此时newClass 与aClass 的相应sno , name 指向同一块内存
  35.         for(int i=0; i<aClass.length; i++) {
  36.             String sno = aClass[i].getSno();
  37.             String name = aClass[i].getName();
  38.             int age = aClass[i].getAge();
  39.             newClass[i] = new Pupil(sno, name, age);
  40.         }
  41.         return newClass;
  42.     }
  43.     public static Pupil[] deeperCopy(Pupil[] aClass) {
  44.         Pupil[] newClass = new Pupil[aClass.length];
  45.         //完全的复制
  46.         for(int i=0; i<aClass.length; i++) {
  47.             String sno = new String(aClass[i].getSno());
  48.             String name = new String(aClass[i].getName());
  49.             int age = aClass[i].getAge();
  50.             newClass[i] = new Pupil(sno, name, age);
  51.         }
  52.         return newClass;
  53.     }
  54. }


2.clone()的使用


* Object.clone()
* Cloneable 接口
* CloneNotSupportedException

a. 使用Object.clone 进行复制
两个必须条件:
1.一定要将重定义后的clone() 方法定义为公有方法(在Object 类中, 它是受保护的成员,    不能直接使用)
2.该后代类声明实现接口 Cloneable 接口(当类实现该接口, 其任何子类也会继承该接口), 该接口实际上没有任何
  内容, 只是一个标识, 标志实现该接口的类提供clone() 方法.(这是接口的一种非典型用法)

  1. public class Fraction implements Cloneable {
  2.     public Object clone() {
  3.         try{
  4.             return super.clone();  //call protected method
  5.         } catch (CloneNotSupportedException e) {
  6.             return null;
  7.         }
  8.     }
  9.     //other methods ...
  10. }



b.重写Object.clone()
例如对   private char[] cb; character buffer 进行复制
  

  1. // add in class Cirbuf
  2.         public Object clone() {
  3.         try{
  4.             Cirbuf copy = (Cirbuf)super.clone();
  5.             copy.cb = (char[])cb.clone();
  6.             return copy;
  7.         }catch (CloneNotSupportedException e){
  8.             throw new InternalError(e.toString());
  9.         }
  10.     }


c.复制数组
  数组是在方法调用重以引用的形式传递的对象. 下述情况下非常适合引用来传递数组:
  *正在接收的方法不修改数组
  *正在调用的方法不必关心是否修改数组
  *正在调用的方法想要得到数组中的修改结果 
  否则, 就应该在方法调用中传递数组对象的副本. 只需调用 arrObj.clone() 方法即可完成数组arrObj 的复制操作. 随后将该数组副本强制转换为其正确类型:
      (type[])arrObj.clone();
   System.arraycopy 方法提供一种用于在数组间复制多个元素的有效方式.
        System.arraycopy(source, i, target, j, len)

3.对象实例的比较


例如:

  1.     Pupil p1 = new Pupil("99184001""zhang3", 18);
  2.     Pupil p2 = new Pupil("99184001""zhang3", 18);


a. "==" 
   if(p1 == p2)...
  此次测试的是对象引用, 其结果肯定是false, 只要两个对象引用不是互为别名就不会相等.
b. 浅比较  false

  1.    if(p1.getSno() == p2.getSno() && p1.getName() == p2.getName()
  2.      && p1.getAge() == p2.getAge()) ...;


c. 深比较   true[/code]   
  if(p1.getSno().equals(p2.getSno()) && p1.getName().equals(p2.getName())
     && p1.getAge() == p2.getAge()) ...;[/code]
    JAVA API 的跟类Object 也提供了equals() 方法, 但它只是比较两个对象引用, 而非比较两个对象实例.
    不管怎样, 如果需要比较Pupil 类的对象(例如要将它们放入对象容器), 应该为Pupil 类重定义equals() 方法:

  1.    
  2.     public boolean equals(Object otherobj) {
  3.         //检查otherobj 是否为空
  4.         if(otherobj == nullreturn false;
  5.         //检查otherobj 是否就是当前对象
  6.         if(otherobj == thisreturn true;
  7.         //检查otherobj 是否具有正确的类型, 即检查是否可与当前对象比较
  8.         if(!(otherobj instanceof Pupil)) return false;
  9.         //将otherobj 转换为Pupil 类的对象引用
  10.         Pupil tmpObj = (Pupil)otherobj;
  11.         //关于学生是否相等的逻辑检查
  12.         if(sno.equals(tmpObj.sno) && name.equals(tmpObj.name)
  13.              && age == tmpObj.age) return true;
  14.         
  15.         return false;
  16.     }


   JAVA API 所提供的每个类几乎都提供了采用深比较策略的equals() 方法, 例如String 类equals() 方法. 一般来说, 用户自己定义的类也应当提供合适的equals() 方法, 特别是当程序要将其对象放入JAVA API 所提供的对象容器类的时候.  
   按照约定, 任何类所提供的equals() 方法所实现的相等比较应该是等价关系, 即满足自反性, 对称性和传递性. 另外一个类重定义了equals() 方法, 也应该重定义相应hashCode() 方法, 否则将这个类的对象放入映射对象容器时也会发生以外.

分享到:
评论

相关推荐

    深入PHP 面向对象 模式与实践第3版(完整版) 35M

    本书全面深入地剖析了面向对象的PHP编程与设计。首先介绍了PHP的OO特性,包括类声明、对象实例化、继承、方法与属性封装以及静态方法与属性、抽象类、接口、异常处理、对象克隆等高级主题。然后介绍了设计模式,阐述...

    深入PHP面向对象、模式与实践 (第2版)》 part2

    首先介绍了php的oo特性,包括类声明、对象实例化、继承、方法与属性封装以及静态方法与属性、抽象类、接口、异常处理、对象克隆等高级主题。然后介绍了设计模式,阐述了模式的概念,展示了如何在php中实现几个关键的...

    深入PHP面向对象、模式与实践 (第2版) part1

    首先介绍了php的oo特性,包括类声明、对象实例化、继承、方法与属性封装以及静态方法与属性、抽象类、接口、异常处理、对象克隆等高级主题。然后介绍了设计模式,阐述了模式的概念,展示了如何在php中实现几个关键的...

    深入php面向对象、模式与实践

    基本数据类型和数组都为真复制,即为真副本,当属性为对象时,为假复制,改变副本仍会影响原对象.解决方案: //在原对象中添加 function __clone(){ $this-&gt;对象 = clone $this-&gt;对象 } __clone在clone前自动触发,可以...

    深入JAVA对象深度克隆的详解

    本篇文章是对JAVA对象深度克隆进行了详细的分析介绍,需要的朋友参考下

    helms:深入JavaScript对象操作

    深度对象复制/比较/合并库。 npm install helms 用法 比较 compare(a: Any, b: Any) -&gt; Boolean 对a与b进行深入比较。 它将在相同的指针和不相等的原型上短路,因此请注意,不同类上的相似属性不相等。 复制 copy...

    深入理解JavaScript中的对象复制(Object Clone)

    JavaScript中并没有直接提供对象复制(Object Clone)的方法。因此下面的代码中改变对象b的时候,也就改变了对象a。 a = {k1:1, k2:2, k3:3}; b = a; b.k2 = 4; 如果只想改变b而保持a不变,就需要对对象a进行复制。 ...

    深入java对象复制的分析

    本篇文章是对java对象复制进行了详细的分析介绍,需要的朋友参考下

    亮剑.NET深入体验与实战精要3

    《.NET深入体验与实战精要》作者身为从事.NET一线开发的资深开发专家,常年耕耘技术博客,惠及无数.NET新知。此次将长期的思考、感悟,多年的系统开发、设计和团队管理经验,以及深入分析众多项目实战的宝贵成果...

    深入了解Java对象的克隆

    主要介绍了Java对象的克隆的相关资料,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下

    对象克隆(clone)详解.docx

    查看了很多文章对于clone()方法讲解都不慎透彻,特别是对于深层克隆的讲解语言晦涩难懂,很难理解,包括Oracle公司出版的JDK帮助文档也讲的不清楚,本人通过...并通过程序对比让大家能够更加深入了解深层克隆的内容。

    C++直接初始化与复制初始化的区别深入解析

    复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象” 还有一段这样说: “通常直接初始化和复制初始化仅在低级别优化上存在差异,然而,对于不支持复制的类型...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part2

    4.12.5 复制节点 134 4.12.6 输出格式化的数字 135 4.13 条件处理 144 4.13.1 [xsl:if] 144 4.13.2 [xsl:choose] 145 4.14 排序 146 4.15 变量和参数 150 4.15.1 变量 150 4.15.2 参数 152 4.16 命名模板 ...

    深入理解:XML与对象的序列化与反序列化

    这篇文章主要讲述XML与对象的序列化与反序列化。并且会附上一些简单的序列化与反序列化方法,供大家使用。假设我们在一个Web项目中有这样两个类复制代码 代码如下:public class Member { public string Num { get; ...

    深入解析Windows操作系统中文.part2.rar

    检查与进程、线程和作业相关的数据结构和算法;观察Windows如何管理虚拟内存和物理内存;理解NTFS的操作和格式,诊断文件系统访问问题;从上往下查看Windows的网络栈,包括映射、API、名称解析和协议驱动程序;诊断...

    Python深入学习之对象的属性

    Python一切皆对象(object),每个对象都可能有多个属性(attribute)。Python的属性有一套统一的管理方案。 属性的__dict__系统 对象的属性可能来自于其类定义,叫做类属性(class attribute)。类属性可能来自类定义自身...

    深入理解JVM内存结构及运行原理全套视频加资料.txt

     第31讲 深入理解对象的访问定位 00:08:01  第32讲 垃圾回收-概述 00:06:20  第33讲 垃圾回收-判断对象是否存活算法-引用计数法详解 00:14:08  第34讲 垃圾回收-判断对象是否存活算法-可达性分析法详解 00:...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part3

    4.12.5 复制节点 134 4.12.6 输出格式化的数字 135 4.13 条件处理 144 4.13.1 [xsl:if] 144 4.13.2 [xsl:choose] 145 4.14 排序 146 4.15 变量和参数 150 4.15.1 变量 150 4.15.2 参数 152 4.16 命名模板 ...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part4

    4.12.5 复制节点 134 4.12.6 输出格式化的数字 135 4.13 条件处理 144 4.13.1 [xsl:if] 144 4.13.2 [xsl:choose] 145 4.14 排序 146 4.15 变量和参数 150 4.15.1 变量 150 4.15.2 参数 152 4.16 命名模板 ...

Global site tag (gtag.js) - Google Analytics