clone() メソッド
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 43/87。
clone() メソッドは、オブジェクトのコピーを作成します。これを使用するには、クラスが Cloneable インターフェースを実装し、Object クラスの clone() メソッドをオーバーライドする必要があります。
public class Person implements Cloneable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public Person clone() {
try {
return (Person) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}これで、オブジェクトの独立したコピーを作成できるようになります:
Person original = new Person("Alice", 25);
Person copy = original.clone();
// copy は同じ値を持つ別のオブジェクトですデフォルトでは、clone() はシャローコピーを実行します。これは、プリミティブ値と参照をコピーすることを意味します。オブジェクトがフィールドとして他のオブジェクトを含んでいる場合、オリジナルとクローンの両方が同じネストされたオブジェクトを参照します。ネストされたオブジェクトを含む真に独立したコピーを作成するには、clone() メソッド内でそれらのネストされたオブジェクトもクローンすることで、ディープコピーを実装する必要があります。
チャレンジ
簡単オブジェクトのクローニングを実演するドキュメント管理システムを構築しましょう。独立したコピーを作成するためにクローン可能な Document クラスを作成し、オリジナルをそのまま保持しながらドキュメントを複製できるようにします。
コードは2つのファイルに分けて構成します:
Document.java: クローニングをサポートするドキュメントを表すクラスを作成します。Document は3つの private フィールドを持ちます:title(String)、author(String)、version(int)。すべてのフィールドを初期化するコンストラクタと、それぞれのゲッターメソッドを含めてください。また、バージョン番号を更新するためのsetVersion(int version)メソッドも追加してください。Document クラスに
Cloneableインターフェースを実装させ、clone()メソッドをオーバーライドしてDocumentを返すようにします。メソッド内ではCloneNotSupportedExceptionをRuntimeExceptionでラップして処理してください。toString()をオーバーライドして、Document[title=X, author=Y, version=Z]を返すようにします。ここで X、Y、Z は実際のフィールド値です。Main.java: ドキュメントを作成してクローンすることで、Document クラスを実際に動かしてみましょう。3つの入力(タイトル (String)、著者 (String)、バージョン番号 (int))を受け取ります。これらの値を使用してオリジナルの Document を作成し、それをクローンしてコピーを作成します。クローン作成後、
setVersion()を使用してコピーのバージョンを 1 増やして変更します。これにより、クローンがオリジナルから真に独立していることが示されます。次の3行を出力してください:
Original:に続けて、オリジナルドキュメントの toString() の内容Clone:に続けて、クローンされたドキュメントの toString() の内容Independent:に続けて、オリジナルとクローンが異なるオブジェクトであるかどうかを示すtrueまたはfalse(!=比較を使用)
3つの入力(ドキュメントのタイトル (String)、著者名 (String)、バージョン番号 (int))を受け取ります。
クローンのバージョンを変更した後も、オリジナルのドキュメントが変更されないことに注目してください。これは clone() が真に独立したコピーを作成したことを証明しています!
チートシート
clone()メソッドはオブジェクトのコピーを作成します。これを使用するには、クラスがCloneableインターフェースを実装し、Objectクラスのclone()メソッドをオーバーライドする必要があります:
public class Person implements Cloneable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public Person clone() {
try {
return (Person) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}独立したコピーの作成:
Person original = new Person("Alice", 25);
Person copy = original.clone();
// copyは同じ値を持つ別のオブジェクトですデフォルトでは、clone()はシャローコピー(浅いコピー)を実行し、プリミティブ値と参照をコピーします。オブジェクトがフィールドとして他のオブジェクトを含んでいる場合、オリジナルとクローンの両方が同じネストされたオブジェクトを参照します。ネストされたオブジェクトを含む真に独立したコピーを作成するには、clone()メソッド内でそれらのネストされたオブジェクトもクローンすることで、ディープコピー(深いコピー)を実装してください。
自分で試してみよう
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 入力を読み込む
String title = scanner.nextLine();
String author = scanner.nextLine();
int version = scanner.nextInt();
// TODO: 入力値を使用してオリジナルのDocumentを作成する
// TODO: オリジナルのドキュメントをクローンしてコピーを作成する
// TODO: クローンのバージョンを1増やして修正する
// TODO: "Original: " に続いてオリジナルのドキュメントを出力する
// TODO: "Clone: " に続いてクローンされたドキュメントを出力する
// TODO: "Independent: " に続いて true/false を出力する (オリジナル != クローン であるかを確認)
}
}このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造7特殊メソッドとObjectクラス
toString() メソッドequals() と hashCode()clone() メソッドcompareTo() と ComparableComparator インターフェースまとめ - カスタムソート