サーチ…


備考

特にオブジェクトのフィールドが他のオブジェクトを保持している場合、クローニングは扱いにくいことがあります。フィールド値(つまり他のオブジェクトへの参照)のみをコピーするのではなく、 ディープコピーを実行したい場合があります。

一番下の行はクローンが壊れているため、 Cloneableインターフェイスを実装してcloneメソッドをオーバーライドする前に2度考える必要があります。 cloneメソッドは、 Cloneableインターフェイスではなく、 Objectクラスで宣言されているため、 Cloneableはパブリックなcloneメソッドがないため、インターフェイスとして機能しません。その結果、 cloneを使用する契約は細かく文書化され、弱く強制されます。例えば、上書きされますクラスclone時々 、オーバーライド、親クラスのすべてに依存しているclone 。彼らはそうするように強制されていませんし、そうでなければあなたのコードは例外をスローするかもしれません。

複製機能を提供するためのもっと良い解決策は、 コピーコンストラクタまたはコピーファクトリを提供することです。 Joshua Blochの「効果的なJava Item 11:慎重にクローンをオーバーライドする」を参照してください。

コピーコンストラクタを使用した複製

オブジェクトを複製する簡単な方法は、コピーコンストラクタを実装することです。

public class Sheep {

    private String name;

    private int weight;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    // copy constructor
    // copies the fields of other into the new object
    public Sheep(Sheep other) {
        this.name = other.name;
        this.weight = other.weight;
    }

}

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// clone the sheep
Sheep dolly = new Sheep(sheep); // dolly.name is "Dolly" and dolly.weight is 20

Clonableインタフェースを実装することによるクローニング

Cloneableインタフェースを実装してオブジェクトを複製する

public class Sheep implements Cloneable {

    private String name;

    private int weight;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// clone the sheep
Sheep dolly =  (Sheep) sheep.clone(); // dolly.name is "Dolly" and dolly.weight is 20

浅いコピーを実行するクローン作成

オブジェクトのクローン作成時のデフォルトの動作は、オブジェクトのフィールドのシャローコピーを実行することです。その場合、元のオブジェクトと複製されたオブジェクトの両方は、同じオブジェクトへの参照を保持します。

この例は、その動作を示しています。

import java.util.List;

public class Sheep implements Cloneable {

    private String name;

    private int weight;

    private List<Sheep> children;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public List<Sheep> getChildren() {
        return children;
    }

    public void setChildren(List<Sheep> children) {
        this.children = children;
    }

}

import java.util.Arrays;
import java.util.List;

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);

// create children
Sheep child1 = new Sheep("Child1", 4);
Sheep child2 = new Sheep("Child2", 5);

sheep.setChildren(Arrays.asList(child1, child2));

// clone the sheep
Sheep dolly =  (Sheep) sheep.clone();
List<Sheep> sheepChildren = sheep.getChildren();
List<Sheep> dollysChildren = dolly.getChildren();
for (int i = 0; i < sheepChildren.size(); i++) {
    // prints true, both arrays contain the same objects
    System.out.println(sheepChildren.get(i) == dollysChildren.get(i));
}

ディープコピーを実行するクローン作成

ネストされたオブジェクトをコピーするには、この例のように詳細コピーを実行する必要があります。

import java.util.ArrayList;
import java.util.List;

public class Sheep implements Cloneable {

    private String name;

    private int weight;

    private List<Sheep> children;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Sheep clone = (Sheep) super.clone();
        if (children != null) {
            // make a deep copy of the children
            List<Sheep> cloneChildren = new ArrayList<>(children.size());
            for (Sheep child : children) {
                cloneChildren.add((Sheep) child.clone());
            }
            clone.setChildren(cloneChildren);
        }
        return clone;
    }

    public List<Sheep> getChildren() {
        return children;
    }

    public void setChildren(List<Sheep> children) {
        this.children = children;
    }

}

import java.util.Arrays;
import java.util.List;

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);

// create children
Sheep child1 = new Sheep("Child1", 4);
Sheep child2 = new Sheep("Child2", 5);

sheep.setChildren(Arrays.asList(child1, child2));

// clone the sheep
Sheep dolly =  (Sheep) sheep.clone();
List<Sheep> sheepChildren = sheep.getChildren();
List<Sheep> dollysChildren = dolly.getChildren();
for (int i = 0; i < sheepChildren.size(); i++) {
    // prints false, both arrays contain copies of the objects inside
    System.out.println(sheepChildren.get(i) == dollysChildren.get(i));
}

コピーファクトリを使用したクローニング

public class Sheep {

    private String name;
    
    private int weight;
    
    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }
    
    public static Sheep newInstance(Sheep other);
        return new Sheep(other.name, other.weight)
    }

}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow