類似用語

ディープコピーとシャローコピーの違い

2019年12月16日

「ディープコピー」と「シャローコピー」の違いって何ですか?
実体をコピーするのが「ディープコピー」実体をコピーしないのが「シャローコピー」です。
なるほど
本記事では、「ディープコピー」と「シャローコピー」の違いについて図解そして実際のソースコードの例を利用して具体的に説明しています。

「ディープコピー」と「シャローコピー」の違い

シャローコピーとは

シャローコピーとは浅い(shallow)コピーと呼ばれ、実体(データ)のコピーを行わないで、オブジェクトをコピーする方式です。要するに見せかけの複製を作るコピーです。

オブジェクトはメモリ上にある実体(データ)を参照します。シャローコピーでは、実体(データ)のコピーを行わないので、シャローコピーで生成されたオブジェクトは、コピー元オブジェクトと同じ実体(データ)を参照することとなります。

シャローコピー

シャローコピーで作られたオブジェクトは、参照している実体(データ)が同じです。ということは、どちらかのオブジェクトを変更したら、もう片方のオブジェクトも変更されます。なぜなら同じ実体(データ)を参照しているからです。

スポンサーリンク

ディープコピーとは

ディープコピーとは深い(deep)コピーと呼ばれ、実体(データ)も含めてオブジェクトをコピーする方式です。要するに完全な複製を作るコピーです。

オブジェクトはメモリ上にある実体(データ)を参照します。ディープコピーでは、オブジェクトと参照する実体(データ)をコピーします。そのため、コピー元とコピー先は別々の実体(データ)を参照することとなります。

ディープコピー

ディープコピーで作られたオブジェクトは、別々の実体(データ)を参照します。そのため、どちらかのオブジェクトを変更しても、もう片方のオブジェクトには影響を与えません

「ディープコピー」と「シャローコピー」のコピー例

シャローコピーのコピー例

コピー対象のオブジェクト(データを格納する箱)は以下とします。

package entity;

public class User {

  private String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}

シャローコピーのコピー例

package main;

import entity.User;

public class Start {

  public static void main(String[] args) {

    User user1 = new User();
    // user1の名前を設定
    user1.setName("変更前の名前");

    // シャローコピー
    User user2 = user1;
    // user2の名前を変更
    user2.setName("変更後の名前");

    System.out.println("user1の名前:" + user1.getName());
    System.out.println("user2の名前:" + user2.getName());
  }
}

スポンサーリンク

実行結果は以下のように「コピー元の名前」「コピー先の名前」には「変更後の名前」が設定されています。

これはどちらもメモリ上にある同じ実体(データ)を参照していることが理由です。

コピー元の名前:変更後の名前
コピー先の名前:変更後の名前

ディープコピーのコピー例

コピー対象のオブジェクト(データを格納する箱)は以下とします。Javaが提供しているclone(複製)を作るインタフェースである「Cloneable」をimplements しています。

package entity;

public class User2 implements Cloneable {

  private String name;

  @Override
    public User2 clone() {
    User2 user2 = null;
        try {
        	user2 = (User2) super.clone();

    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }

        return user2;
    }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}

ディープコピーのコピー例

package main;

import entity.User2;

public class Start2 {

  public static void main(String[] args) {

    User2 user2 = new User2();
    // user1の名前を設定
    user2.setName("変更前の名前");

    // ディープコピー
    User2 copyUser2 = user2.clone();
    // user2の名前を変更
    copyUser2.setName("変更後の名前");

    System.out.println("コピー元の名前:" + user2.getName());
    System.out.println("コピー先の名前:" + copyUser2.getName());
  }
}

実行結果は以下のように「コピー元の名前」「コピー先の名前」には別々の名前が設定されています。

これはシャローコピーとは違い、メモリ上にある別の実体(データ)を参照していることが理由です。

コピー元の名前:変更前の名前
コピー先の名前:変更後の名前

helpful