dedecms织梦内容管理系统    
首页 | java | C/C++ | PHP | 操作系统 | ajax | 脚本编程 | 安全技术 | 本站下载页 | flex | CRM | 专题 | QQ群 | 测试中心 | 会员中心 | 积分规则
  当前位置:主页>java>java基础>文章内容
深入 JAVA对象的复制与比较
来源:赛迪网 作者:

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

1.对象的复制


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

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

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


2.clone()的使用


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

a. 使用Object.clone 进行复制
两个必须条件:
1.一定要将重定义后的clone() 方法定义为公有方法(在Object 类中, 它是受保护的成员,    不能直接使用)
2.该后代类声明实现接口 Cloneable 接口(当类实现该接口, 其任何子类也会继承该接口), 该接口实际上没有任何
  内容, 只是一个标识, 标志实现该接口的类提供clone() 方法.(这是接口的一种非典型用法)
  1.  
  2. public class Fraction implements Cloneable {
  3.     public Object clone() {
  4.         try{
  5.             return super.clone();  //call protected method
  6.         } catch (CloneNotSupportedException e) {
  7.             return null;
  8.         }
  9.     }
  10.     //other methods ...
  11. }


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.  
  2.     Pupil p1 = new Pupil("99184001", "zhang3", 18);
  3.     Pupil p2 = new Pupil("99184001", "zhang3", 18);

a. "==" 
   if(p1 == p2)...
  此次测试的是对象引用, 其结果肯定是false, 只要两个对象引用不是互为别名就不会相等.
b. 浅比较  false
  1.  
  2.    if(p1.getSno() == p2.getSno() && p1.getName() == p2.getName()
  3.      && 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 == null) return false;
  5.  
  6.         //检查otherobj 是否就是当前对象
  7.         if(otherobj == this) return true;
  8.  
  9.         //检查otherobj 是否具有正确的类型, 即检查是否可与当前对象比较
  10.         if(!(otherobj instanceof Pupil)) return false;
  11.  
  12.         //将otherobj 转换为Pupil 类的对象引用
  13.         Pupil tmpObj = (Pupil)otherobj;
  14.         //关于学生是否相等的逻辑检查
  15.         if(sno.equals(tmpObj.sno) && name.equals(tmpObj.name)
  16.              && age == tmpObj.age) return true;
  17.         
  18.         return false;
  19.     }

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

上一篇:java多线程编程   下一篇:Vector & ArrayList 哪一个更好?为什么
[收藏] [推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
用户名: 新注册) 密码: 匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论
  热点文章
·JUnit单元测试(2)
·JUnit单元测试(1)
·浅谈在Java语言中究竟是传值还是
·Java 5.0 多线程编程实践
·Java的文件 读和写
·对于JAVA基础测试中常见的异常问
·JAVA程序员面试33问,你能回答多
·Java Reflection (JAVA反射)详解
·JAVA中配置环境变量设置方法大全
·讲述java语言中内部类的研究
·详细解析Java中抽象类和接口的区
·Java开发中的事件驱动模型实例详
  相关文章
·java多线程编程
·Vector & ArrayList 哪一个更好
·java学习----理解面向对象的程序
·Java语言的克隆与深层次克隆技术
·Java语言的参数传递和处理方法 -
·Java/J2EE中文问题终极解决之道
·怎么向一个命令行Java程序传递参
·讨论 Java 技术新手入门
·Java输入输出(Java IO)处理概
·Java开发者需坚守的十大基本准则
·JAVA如何调用DOS命令
·如何使用Static的变量和方法
  相关信息
copy right @ 百家拳软件项目研究室 2007 辽ICP备07011763