ITエンジニアの成長ブログ

ITエンジニアとして行う勉強の発信&日々の生活で体験した楽しいことをゆるく発信

Javaのシャロ―コピーとディープコピーについて

タイトル通り、Javaのシャロ―コピーとディープコピーについて簡単にお話していきたいと思います。

シャロ―コピー(Shallow Copy)とは?

シャロ―コピーとは英訳すると、「浅いコピー」となります。簡単にJavaのコードで説明したいと思います。

以下のようなUserクラスを用意します。

public class User {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

上記のUserクラスを以下のようにSampleクラスで使用して、実行してみます。

public class Sample {
    public static void main(String[] args) {
        User user1 = new User();
        user1.setId(1);
        user1.setName("たろう");
        System.out.println("user1のid = " + user1.getId());
        System.out.println("user1のname = " + user1.getName());

        User user2 = user1;
        user2.setName("おさむ");
        System.out.println("user1のid = " + user1.getId());
        System.out.println("user1のname = " + user1.getName());
        System.out.println("user2のid = " + user2.getId());
        System.out.println("user2のname = " + user2.getName());
    }
}

出力結果は以下のようになると思います。
user2のnameを変更したらuser2のnameはもちろん、user1のnameも変更されてしまいました。

user1のid = 1
user1のname = たろう
user1のid = 1
user1のname = おさむ
user2のid = 1
user2のname = おさむ

以下のコードでuser2にuser1の参照している場所を代入することで、
user1とuser2はそれぞれ同じオブジェクトを指していることになります。

User user2 = user1;

これがシャロ―コピーと呼ばれるものです。しかし、場合によっては別のUserを作成してそれぞれ別のオブジェクトで扱いたい場合ももちろんあると思います。その場合に使うのが「ディープコピー」と呼ばれるものです。

ディープコピー(Deep Copy)とは?

シャロ―コピーとは英訳すると、「深いコピー」となります。こちらも簡単にJavaのコードで説明したいと思います。

Userクラスはシャロ―コピーで説明したものを使用します。Sampleクラスのみ以下のように変更します。

public class Sample {
    public static void main(String[] args) {
        User user1 = new User();
        user1.setId(1);
        user1.setName("たろう");
        System.out.println("user1のid = " + user1.getId());
        System.out.println("user1のname = " + user1.getName());

        //User user2 = user1;
        User user2 = new User();
        BeanUtils.copyProperties(user2, user1);
        user2.setName("おさむ");
        System.out.println("user1のid = " + user1.getId());
        System.out.println("user1のname = " + user1.getName());
        System.out.println("user2のid = " + user2.getId());
        System.out.println("user2のname = " + user2.getName());
    }
}

出力結果は以下のようになると思います。
今回は、user2のnameを変更してもuser1のnameは変更されませんでした。

user1のid = 1
user1のname = たろう
user1のid = 1
user1のname = たろう
user2のid = 1
user2のname = おさむ

上記ディープコピーの処理は以下のところです。今回は便利なライブラリの力をお借りしています。

        User user2 = new User();
        BeanUtils.copyProperties(user2, user1);

ライブラリの細かい説明は省きますが、上記の処理によりディープコピーを行うと、まったく別のオブジェクトとしてコピーされることになります。

以下に、一応ライブラリのリンクを張っておきます。
BeanUtils (Apache Commons BeanUtils 1.9.4 API)

おわりに

いかがでしょうか。シャロ―コピーとディープコピーについて簡単ですが、説明させていただきました。Javaのオブジェクトの参照の部分は基本的なところではありますが、しっかり理解できていないとバグになりうる問題ですので、気を付けて実装していきたいところです。

今回はこの辺で失礼いたします。最後までお読みいただきありがとうございました。