Javaのインスタンスのコピーについて現役エンジニアが解説【初心者向け】

初心者向けにJavaのインスタンスのコピーについて解説しています。インスタンスのコピーには浅いコピーと呼ばれるもの、深いコピーと呼ばれるものの2つがあります。それぞれの違いと書き方、使用例を見ていきましょう。

TechAcademyマガジンは受講者数No.1のオンラインプログラミングスクールTechAcademy [テックアカデミー]が運営。初心者向けに解説した記事を公開中。現役エンジニアの方はこちらをご覧ください。

Javaのインスタンスのコピーについて、TechAcademyのメンター(現役エンジニア)が実際のコードを使用して初心者向けに解説します。

 

Javaについてそもそもよく分からないという方は、Javaとは何なのか解説した記事を読むとさらに理解が深まるでしょう。

 

なお本記事は、TechAcademyのオンラインブートキャンプ、Java講座の内容をもとに作成しています。

 

田島悠介

今回は、Javaに関する内容だね!

大石ゆかり

どういう内容でしょうか?

田島悠介

インスタンスのコピーについて詳しく説明していくね!

大石ゆかり

お願いします!

 

目次

 

インスタンスとは

インスタンスとは、クラスをから生成されるオブジェクトのことです。

また、クラスをもとにオブジェクトを生成することをインスタンス化と呼び、インスタンスを生成するとメモリ上のインスタンスが作られた場所を示す参照が作られます。

 

[PR] Javaで挫折しない学習方法を動画で公開中

浅いコピーと深いコピーの違い

インスタンスをコピーする場合、浅いコピーと深いコピー2つの方法があります。

浅いコピーは、インスタンス自体はコピーされて別のインスタンス扱いになっているものの、中のメンバ変数の参照先が変わっていないコピー方法のことです。

この方法でコピーすると、インスタンスのメンバ変数を変更した場合、もう一方のインスタンスのメンバ変数も同時に変更される点に注意しましょう。

 

対して、深いコピーはメンバ変数の参照先の実体も含めてコピーされます。

別々のメモリ上のオブジェクトの実体を見に行くようにコピーするため、一方のインスタンスの値を変更しても、もう一方のインスタンスの値には影響なく変更可能です。

深いコピーを実現するには以下のようにクラスを記述しておきましょう。

 

class クラス名 implements Cloneable{
  参照型 メンバ変数01;
  プリミティブ型 メンバ変数02;
  public Object clone(){
    try{
      クラス名 変数名=(クラス名)super.clone();
      変数名.メンバ変数 = new 参照型(メンバ変数01);
      return変数名;
    }catch(CloneNotSupportedException ex){
      return null;
    }
  }
}

コピーするときは以下のように記述しましょう。

クラス名 コピー前 = new クラス名();
クラス名 コピー後 = コピー前.clone();

作成したcloneメソッドを使うことでコピーを実現可能です。

 

実際に書いてみよう

Javaのインスタンスの浅いコピーと深いコピーを実際にソースで書いてみましょう。

ソースコード

public class  SampleClass {
  public static void main(String[] args) {
    System.out.println("==浅いコピー==");
    Sample01 sample01 = new Sample01();
    sample01.str = new StringBuffer("あいうえお");
    Sample01 sample02 = (Sample01) sample01.clone();
    sample02.str.append("かきくけこ");
    System.out.println(sample01.str);
    System.out.println(sample02.str);

    System.out.println("==深いコピー==");
    Sample02 sample03 = new Sample02();
    sample03.str = new StringBuffer("あいうえお");
    Sample02 sample04 = (Sample02) sample03.clone();
    sample04.str.append("かきくけこ");
    System.out.println(sample03.str);
    System.out.println(sample04.str);
  }
}

class Sample01 implements Cloneable {
  StringBuffer str;
  public Object clone() {
    try {
      Sample01 sample=(Sample01)super.clone();
      return sample;
    } catch(CloneNotSupportedException ex) { return null; }
  }
}
class Sample02 implements Cloneable{
  StringBuffer str;
  public Object clone() {
    try {
      Sample02 sample=(Sample02)super.clone();
      sample.str = new StringBuffer(str);
      return sample;
    }catch(CloneNotSupportedException ex){ return null; }
  }
}

 

実行結果

==浅いコピー==
あいうえおかきくけこ
あいうえおかきくけこ
==深いコピー==
あいうえお
あいうえおかきくけこ

 

浅いコピーではインスタンスの実体はコピーされたものの、中の参照型のメンバ変数の参照先はそのままなので、コピー先のインスタンスのメンバ変数を変更するとコピー元のメンバ変数も変わっています。

一方、深いコピーでは、参照型のメンバ変数の参照先も含めてコピーしているため、コピー先のインスタンスのメンバ変数を変更してもコピー元のメンバ変数は変わりません。

 

まとめ

この記事ではJavaのインスタンスの浅いコピーと深いコピーについて解説しました。

 

執筆してくれたメンター

メンターSさん

システムエンジニアとしてこれまで行政システムや医療用システムの保守、開発に携わりました。

JavaやPython、PHP、Kotlinなど様々な言語での開発経験があります。

TechAcademyではJavaコース、Pythonコース、AIコースなど7コースを担当しています。

 

大石ゆかり

Javaのインスタンスのコピーがよく分かったので良かったです!

田島悠介

ゆかりちゃん、これからも分からないことがあったら質問してね!

大石ゆかり

分かりました。ありがとうございます!

 

TechAcademyでは、初心者でも最短4週間で、JavaやServletの技術を使ってWebアプリケーション開発を習得できるオンラインブートキャンプを開催しています。

また、現役エンジニアから学べる無料体験も実施しているので、ぜひ参加してみてください。