Java 入門

ホーム > Java の基本 > オブジェクトのクローン

オブジェクトのクローン

コピーとクローンの問題点

オブジェクトのコピーを作る時には、そのオブジェクトが持つ参照に注意が必要です。

次のコードを見てください。

Person p1 = new Person();
Person p2 = p1;
    
p1.setAge(30);

この例では Person クラスのオブジェクト p1 が p2 に代入されています。

このようにすると、p2 は p1 が指しているオブジェクトと全く同じオブジェクトを指し示します。 すると、p1 に行った変更が p2 にも影響することになります。(実体は全く同じものですから当然ですね)

clone メソッドの利用

他の変数に対して行った操作の影響を避けるためには、clone メソッドを利用します。

clone メソッドは Object クラスにて定義されており、二つのオブジェクトをフィールド毎に値を丸コピーします。

上のコード例の p1 と p2 が互いに変更の影響を受け合わないようにするには、clone メソッドを用いて次のようにします。

Person p1 = new Person();
Person p2 = p1.clone();
    
p1.setAge(30);

clone メソッドによって、異なるオブジェクトが作成され、かつフィールドの値が丸コピーされるので互いの変数 (上の場合 p1 と p2)が影響を与え合うことが無くなります。

ただし、あくまでフィールドの値のコピーになるので、フィールドに値を変更可能なオブジェクトがセットされていると問題が発生します。 フィールドにオブジェクトがセットされている場合、それらのコピーになるので、上述のようにオブジェクトのコピーによるデータ共有の問題が生じるからです。

このため、クローン可能なオブジェクトを作るには、そのクラスの clone メソッドにて、クローン方法を正しく定義する必要があります。

Cloneable インターフェイスと clone メソッドの定義

上術のようなオブジェクトのコピー・クローンの問題を解決するには、Cloneable インターフェイスを実装し clone メソッドを定義し直します。

public class Person implements Cloneable {
  Class1 o;
  ...
  
  public Person clone() throws CloneNotSupportedException {
    Person cloned = (Personsuper.clone();
    cloned.o = (Class1o.clone();
    return cloned;
  }
}

public class Class1 implements Cloneable {
  ...

  public Class1 clone() throws CloneNotSupportedException {
    return (Class1super.clone();
  }
}

このように、clone メソッドを定義する場合は、その内部のオブジェクトも正しくクローンされるように注意してください。

ホーム > Java の基本 > オブジェクトのクローン