科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航



ZDNet>软件频道>中间件-zhiding>JAVA对象复制与比较

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

一般来说, 用户自己定义的类也应当提供合适的equals() 方法, 特别是当程序要将其对象放入JAVA API 所提供的对象容器类的时候。

来源: 2008年02月13日

关键字:java 对象 复制 比较

1.对象的复制

  2.clone()的使用

  3.对象实例的比较

  ////////////////////

  //

  /////////////////////

  1.对象的复制

  String str1 = "This is a string!" //这里是 "对象引用" 的复制

  String str2 = new String(str1); //这里是 "对象实例" 的复制

  浅复制: 只复制复合对象本身.

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

  例如:

  class Pupil{

  public Pupil(String sno, String name, int age){

  this.sno = new String(sno);

  this.name = new String(name);

  this.age = age;

  }

  public String getSno() {

  return sno;

  }

  public String getName() {

  return name;

  }

  public int getAge() {

  return age;

  }

  public void setAge(int age) {

  this.age = age;

  }

  private String sno;

  private String name;

  private int age;

  }

  public class CopyDemo {

  public static Pupil[] shallowCopy(Pupil[] aClass) {

  Pupil[] newClass = new Pupil[aClass.length];

  //此时newClass 与aClass 指向同一块内存

  for(int i=0; i

  newClass[i] = aClass[i];

  return newClass;

  }

  public static Pupil[] deepCopy(Pupil[] aClass) {

  Pupil[] newClass = new Pupil[aClass.length];

  //此时newClass 与aClass 的相应sno , name 指向同一块内存

  for(int i=0; i

  String sno = aClass[i].getSno();

  String name = aClass[i].getName();

  int age = aClass[i].getAge();

  newClass[i] = new Pupil(sno, name, age);

  }

  return newClass;

  }

  public static Pupil[] deeperCopy(Pupil[] aClass) {

  Pupil[] newClass = new Pupil[aClass.length];

  //完全的复制

  for(int i=0; i

  String sno = new String(aClass[i].getSno());

  String name = new String(aClass[i].getName());

  int age = aClass[i].getAge();

  newClass[i] = new Pupil(sno, name, age);

  }

  return newClass;

  }

  }

  2.clone()的使用

  * Object.clone()

  * Cloneable 接口

  * CloneNotSupportedException

  a. 使用Object.clone 进行复制 两个必须条件:

  1.一定要将重定义后的clone() 方法定义为公有方法(在Object 类中, 它是受保护的成员, 不能直接使用)

  2.该后代类声明实现接口 Cloneable 接口(当类实现该接口, 其任何子类也会继承该接口), 该接口实际上没有任何

  内容, 只是一个标识, 标志实现该接口的类提供clone() 方法.(这是接口的一种非典型用法)

  public class Fraction implements Cloneable {

  public Object clone() {

  try{

  return super.clone(); //call protected method

  } catch (CloneNotSupportedException e) {

  return null;

  }

  }

  //other methods ...

  }

  b.重写Object.clone()

  例如对 private char[] cb; character buffer 进行复制

  // add in class Cirbuf

  public Object clone() {

  try{

  Cirbuf copy = (Cirbuf)super.clone();

  copy.cb = (char[])cb.clone();

  return copy;

  }catch (CloneNotSupportedException e){

  throw new InternalError(e.toString());

  }

  }

  c.复制数组

  数组是在方法调用重以引用的形式传递的对象. 下述情况下非常适合引用来传递数组:

  *正在接收的方法不修改数组

  *正在调用的方法不必关心是否修改数组

  *正在调用的方法想要得到数组中的修改结果

  否则, 就应该在方法调用中传递数组对象的副本. 只需调用 arrObj.clone() 方法即可完成数组arrObj 的复制操作. 随后将该数组副本强制转换为其正确类型:

  (type[])arrObj.clone();

  System.arraycopy 方法提供一种用于在数组间复制多个元素的有效方式.

  System.arraycopy(source, i, target, j, len)

  3.对象实例的比较

  例如:

  Pupil p1 = new Pupil("99184001", "zhang3", 18);

  Pupil p2 = new Pupil("99184001", "zhang3", 18);

  a. "=="

  if(p1 == p2)...

  此次测试的是对象引用, 其结果肯定是false, 只要两个对象引用不是互为别名就不会相等.

  b. 浅比较 false

  if(p1.getSno() == p2.getSno() && p1.getName() == p2.getName()

  && 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() 方法:

  public boolean equals(Object otherobj) {

  //检查otherobj 是否为空

  if(otherobj == null) return false;

  //检查otherobj 是否就是当前对象

  if(otherobj == this) return true;

  //检查otherobj 是否具有正确的类型, 即检查是否可与当前对象比较

  if(!(otherobj instanceof Pupil)) return false;

  //将otherobj 转换为Pupil 类的对象引用

  Pupil tmpObj = (Pupil)otherobj;

  //关于学生是否相等的逻辑检查

  if(sno.equals(tmpObj.sno) && name.equals(tmpObj.name)

  & age == tmpObj.age) return true;

  return false;

  }

  JAVA API 所提供的每个类几乎都提供了采用深比较策略的equals() 方法, 例如String 类equals() 方法. 一般来说, 用户自己定义的类也应当提供合适的equals() 方法, 特别是当程序要将其对象放入JAVA API 所提供的对象容器类的时候.

  按照约定, 任何类所提供的equals() 方法所实现的相等比较应该是等价关系, 即满足自反性, 对称性和传递性. 另外一个类重定义了equals() 方法, 也应该重定义相应hashCode() 方法, 否则将这个类的对象放入映射对象容器时也会发生以外。
推广二维码
邮件订阅

如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

重磅专题