疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

java中对象的复制与相等判断


 

  一、基本概念

  1.基本数据类型,采用的是值传递

  2.对象类型采用引用传递,即如果修改复制对象,源对象也会发生改变

  二、实现深复制的方法:(连同基本数据类型和对象的引用以及被引用的对象本身都复制一遍。所以深复制后的对象和原对象是两个完全不同的对象,只不过其返回的类型是一样的。)

  1.java对象实现cloneable接口

  1.1 java对象默认继承java.long.Object类,里面包含clone方法。JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点:一是拷贝对象是一个新对象,而不是一个引用。二是拷贝对象与用new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。

  1.2重写clone方法

  1.3方法内调用super.clone方法

  比如:

  public class EntityDO implements Cloneable{

  String name;

  String phone;

  String address;

  public EntityDO(String name, String phone, String address) {

  super();

  this.name = name;

  this.phone = phone;

  this.address = address;

  }

  public Object clone() {

  Object o = null;

  try {

  o = (EntityDO) super.clone();// Object中的clone()识别出你要复制的是哪一个对象。

  } catch (CloneNotSupportedException e) {

  System.out.println(e.toString());

  }

  return o;

  }

  public static void main(String args[]) {

  EntityDO do1 = new EntityDO("1","1","1");

  EntityDO do2 = do1;

  do2.setName("11");

  EntityDO do3 = (EntityDO) do1.clone();

  do3.setName("22");

  if (do1 == do2) {

  System.out.println("true");

  } else {

  System.out.println("false");

  }

  System.out.println(do1.getName());

  if (do1 == do3) {

  System.out.println("true");

  } else {

  System.out.println("false");

  }

  System.out.println(do1.getName());

  }

  }

  输出结果为:true 11 false 11

  解释下java对象使用==进行比较的返回值。对于基本类型比较的是值,对于对象来说比较的是地址。在写一个类的时候,一般重写对象的equals()方法,Object类的equals方法默认是使用==来进行比较的。

  注意1:Cloneable接口是不包含任何方法的!其实这个接口仅仅是一个标志,而且这个标志也仅仅是针对Object类中clone()方法的,如果clone类没有实现Cloneable接口,并调用了Object的clone()方法(也就是调用了super.Clone()方法),那么Object的clone()方法就会抛出CloneNotSupportedException异常。

  注意2:如果对象里还包含着其他对象,那被包含的对象应该也按要求来的。且在对象的clone()方法内,对被包含对象进行clone,不然该包含的对象进行的是浅复制。

  比如:CloneA,CloneB 两者都满足上述所说条件,对CloneA的clone()方法进行改写

  public class CloneA implements Cloneable{

  CloneB b;

  public Object clone(){

  CloneA o = null;

  try{

  o = (CloneA)super.clone();

  }catch(CloneNotSupportedException e){

  e.printStackTrace();

  }

  o.b = (CloneB)b.clone();

  return o;

  }

  }

  要注意有些java类不能实现clone这种方案,且对象包含关系比较复杂的时候,这种方案不可取。

  2.利用对象的序列化和反序列化来实现对象的clone

  序列化是指:把java对象转化为字节流。反序列化:把字节流转为java对象

  注意:虽然Java的序列化非常简单、强大,但是要用好,还有很多地方需要注意。比如曾经序列化了一个对象,可由于某种原因,该类做了一点点改动,然后重新被编译,那么这时反序列化刚才的对象,将会出现异常

  2.1 利用序列化来实现深层clone,则在相应的函数里应该这样写:将对象写入到流内,然后将流反序列化到对象,返回对象。

  注意:如果有的对象不能实现序列化,则要考虑该对象可否设成transient,从而将之排除在复制过程之外

  例子:

  //写入到流里面去

  ByteArrayOutoutStream bo=new ByteArrayOutputStream();

  ObjectOutputStream oo=new ObjectOutputStream(bo);

  oo.writeObject(this);

  //从流里读出来

  ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());

  ObjectInputStream oi=new ObjectInputStream(bi);

  return(oi.readObject());

  主要的两个:ObjectInputeStream ObjectOutputStream.这两个对象流都是由包含对象字节流构造而成。