Javaオブジェクトの深度コピーと浅いコピーの実例の詳細


Javaオブジェクトの深度コピーと浅いコピーの実例の詳細
私たちはいくつかのビジネスシーンに遭遇した時に、常にオブジェクトを複製する必要があります。対象のコピーには主に2つの方法があります。
浅いコピー:オブジェクトのコピーはオブジェクト自身だけで、オブジェクト参照の他の相手はコピーされません。
深度コピー:オブジェクトのコピーには、オブジェクト参照を含むオブジェクトが含まれます。
Javaのすべてのオブジェクトのベースはclone方法を提供していますが、この方法はprotected native修飾なので、暴露するだけで書き換えます。外部から直接に呼び出すことはできません。
私たちは今二つのコピーをテストします。まず浅い複製で、浅い複製でCloeableインターフェースを実現します。

//     
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 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();
    }

例外として、生成対象の5つの方法について述べます。
1.new
2.Class類のnewInstance
3.コンストラクタ類newInstance
4.Clone方式
5.反秩序化の方式
その中の2と3は反射の方式です。
読んでくれてありがとうございます。みなさんのご協力をお願いします。ありがとうございます。