`

深入对象复制与比较

    博客分类:
  • 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() 方法, 否则将这个类的对象放入映射对象容器时也会发生以外.

分享到:
评论

相关推荐

    JAVA_对象克隆

    二、浅克隆与深克隆 1. 浅克隆:默认的`clone()`方法执行的是浅克隆,它创建的新对象只复制原始对象的基本数据类型字段,对于引用类型的字段,新对象和原始对象共享同一个引用。这意味着对引用对象的修改会影响到...

    java不同对象及集合的多次复制

    在Java编程中,对象复制是一项常见的任务,特别是在处理模型(Model)和视图对象(VO)时。模型对象通常用于封装业务数据,而视图对象则用于展示这些数据。值复制,即对象属性值的复制,是保持数据一致性和简化代码...

    clone 深度克隆对象

    本文将深入探讨"深度克隆"这一概念,以及它与普通克隆的区别,并讨论其在实际应用中的优缺点。 深度克隆,也称为完全克隆,是一种创建新对象的技术,这个新对象不仅包含原始对象的所有属性值,还包含了嵌套对象的...

    Java对象的深克隆与浅克隆详解.zip(wcb2003)

    在Java编程语言中,克隆是一种创建对象副本的技术,它允许我们复制一个对象的状态而不影响原始对象。...在设计类和系统时,应考虑对象复制的需求,并决定是否实现`Cloneable`接口,以及选择哪种克隆策略。

    clone()方法示例(对象克隆)_对象克隆_nervouse78_源码

    在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在处理对象复制和数据持久化时。本示例将深入探讨`clone()`方法的工作原理、使用场景以及如何在实际编程中应用。首先,我们来理解一下`clone()`方法的...

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

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

    C++程序设计与实践:07-第6章 深入类和对象.ppt

    本资源摘要信息涵盖了深入类和对象的知识点,包括深复制和浅复制、禁止复制、对象的三种创建方法、对象的初始化方法、this指针、指向类对象的指针、指向类成员的指针、友元关系等,为学习C++程序设计与实践的学生...

    类继承与对象复制的细节.zip_类继承与对象复制的细节

    通过深入理解类继承和对象复制的细节,开发者能够更有效地设计和实现复杂的面向对象程序,提高代码的可读性、可维护性和复用性。在实践中,合理运用这些概念可以优化程序结构,减少代码冗余,提升软件质量。

    深度探索c++对象模型(2012版本)

    此外,拷贝构造函数和赋值运算符也至关重要,它们处理对象的复制和赋值,确保数据的正确处理。 在C++中,类是定义对象的蓝图,而对象是类的实例。每个类可以有成员变量和成员函数,其中成员函数(方法)负责对象的...

    编程语言java对象复制.pdf

    通过以上知识点,可以看出Java中的对象复制是一个涉及多个方面的复杂问题,理解并正确实现对象的深复制,需要对Java的继承、接口、异常处理等有深入的理解。在实际开发中,应仔细考虑对象的复制需求,选择合适的方式...

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

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

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

    《深入 PHP 面向对象、模式与实践》一书深入探讨了 PHP 编程中的面向对象技术、设计模式以及最佳实践。以下是对这些概念的详细解释: 1. **克隆(Clone)** - `clone` 关键字用于创建一个对象的副本,通常是为了...

    《面向对象技术与方法》07、类与对象.pdf

    当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。 - **分代收集算法**:根据对象存活周期的不同将内存划分为几块。一般是将Java堆分为新生代和老年代,这样...

    BeanUtilsBean对象复制使用(类型可以自动转化)

    本文将深入探讨`BeanUtilsBean`对象复制的功能,特别关注它如何实现类型自动转换。`BeanUtilsBean`是BeanUtils的核心类,提供了对JavaBean属性的便捷访问和操作。 首先,让我们理解什么是对象复制。对象复制是指将...

    深入了解Java对象的克隆

    克隆是指在内存中创建一个新的对象,该对象复制了原始对象的所有属性和值。这一概念的引入,主要是为了解决对象间相互影响的问题。以对象引用为例,如果两个变量指向同一个对象,任何一个变量所做的修改都会直接反映...

    java对象复制[参考].pdf

    本文将深入探讨Java对象复制,特别是通过`clone()`方法实现的复制。 首先,我们来理解什么是对象复制。对象复制是指创建一个新对象,这个新对象与原对象具有相同的属性值。在Java中,基础类型(如int、double等)是...

    深入分析php之面向对象

    以上内容详尽地解释了PHP面向对象编程中的`final`关键字、`__toString`方法、接口与抽象类、对象引用传递、克隆对象以及魔术方法的概念和用法,这些都是理解和编写高效、灵活的PHP代码所必需的基础知识。

    深入C++对象模型 by stanley B. Lippman

    - **拷贝构造函数构造**:讨论拷贝构造函数如何复制对象及其应用场景。 - **程序转换语义**:阐述如何通过程序转换技术改善性能。 #### 结论 《深入C++对象模型》是一本专为希望深入了解C++内部机制的高级程序员...

    《面向对象技术与方法》08、类与对象.pdf

    《面向对象技术与方法》08、类与对象这一章节深入探讨了类与对象的基本概念及其操作,下面我们将详细解析其中的关键知识点。 ### 类与对象的基本概念 类是面向对象编程中用于定义对象的蓝图或模板,它描述了一组...

    java类复制一个持久化对象

    在Java编程语言中,对象复制是一项常见的操作,尤其是在处理持久化对象时,为了保持数据的一致性和完整性,正确地复制对象变得尤为重要。本文将深入探讨如何利用反射机制在Java中复制一个持久化对象,理解其背后的...

Global site tag (gtag.js) - Google Analytics