欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java对象深复制与浅复制实例详解

程序员文章站 2024-02-20 08:57:16
 java对象深复制与浅复制实例详解 我们在遇到一些业务场景的时候经常需要对对象进行复制,对于对象的复制一般有两种方式,深复制和浅复制 浅复制:对象的复制仅是...

 java对象深复制与浅复制实例详解

我们在遇到一些业务场景的时候经常需要对对象进行复制,对于对象的复制一般有两种方式,深复制和浅复制

浅复制:对象的复制仅是对象本身,对象引用的其它对方并不会复制。

深复制:对象的复制包含对象引用的对象。

java所有对象的基类提供了clone方法,但是这个方法是protected native修饰,因此只暴露给之类去重写,外部是无法直接调用的。

我们现在来测试两种复制,首选是浅复制,浅复制要实现cloneable接口。

// 课程对象
class class {
  private string name;

  public string getname() {
    return name;
  }

  public void setname(string name) {
    this.name = name;
  }

}
// 学生对象
class user implements cloneable {
  private string name;
  private long id;
  // 课程引用
  private class c;

  public class getc() {
    return c;
  }

  public void setc(class c) {
    this.c = c;
  }

  public string getname() {
    return name;
  }

  public void setname(string name) {
    this.name = name;
  }

  public long getid() {
    return id;
  }

  public void setid(long id) {
    this.id = id;
  }

  @override
  protected object clone() throws clonenotsupportedexception {
    return super.clone();
  }

  @override
  public int hashcode() {
    return super.hashcode();
  }

  @override
  public boolean equals(object obj) {

    if (obj instanceof user) {
      user user = (user) obj;
      if (this.id == user.getid() && this.getname() == user.getname()) {
        return true;
      }
      if (user.getid().equals(this.id)
          && user.getname().equals(this.name)) {
        return true;
      }
      return false;
    } else
      return false;
  }

}

我们来测试:

 user user1 = new user();
    user user2 = user1;

    user user3 = (user) user1.clone();

    system.out.println(user1 == user2);
    system.out.println(user3 == user1);
    system.out.println(user3.equals(user1));
    system.out.println(user3.getname() == user3.getname());// true,浅复制

    class c = new class();
    c.setname("语文");
    user1.setc(c);
    // 测试复制深度
    user user4 = (user) user1.clone();
    system.out.println(user4.getc() == user1.getc()); // true,说明引用的对象依然是同一个对象

对象的复制并没复制引用所指向的对象class,复制出来的引用指向的同一个地址。

深复制采用序列化与反序列的方式去获取,也有种说法类似于腌菜,用流的方式腌制进去又取出来,实现深度复制。

class car implements serializable {
  /**
   * 
   */
  private static final long serialversionuid = 42342l;
  private string name;

  public string getname() {
    return name;
  }

  public void setname(string name) {
    this.name = name;
  }

}

// 深复制
class people implements serializable{
  /**
   * 
   */
  private static final long serialversionuid = 543535212412l;
  private car car;

  public car getcar() {
    return car;
  }

  public void setcar(car car) {
    this.car = car;
  }

  public people deepclone() throws ioexception, classnotfoundexception {
    // 腌制
    bytearrayoutputstream out = new bytearrayoutputstream();
    objectoutputstream oos = new objectoutputstream(out);
    oos.writeobject(this);
    // 取出
    bytearrayinputstream input = new bytearrayinputstream(out.tobytearray());
    objectinputstream ois = new objectinputstream(input);
    return (people) ois.readobject();
  }

}

测试深复制:

// 深复制
    car car = new car();
    car.setname("benz");
    people p = new people();
    p.setcar(car);

    try {
      people p2 = p.deepclone();
      system.out.println(p2.getcar() == p.getcar()); // false,说明引用的对象也进行了复制
    } catch (classnotfoundexception | ioexception e) {
      e.printstacktrace();
    }

例外提及一下生成对象的五种办法:

1.new
2.class类的newinstance
3.constructor类newinstance
4.clone方式
5.反序列化的方式

其中2与3即是反射的方式。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!