java.lang.Object
clone()
Java でのメソッドのデフォルト実装を提供します。Object
クラスで保護およびネイティブとして宣言されているため、ネイティブ コードで実装されます。clone()
メソッドを呼び出してオブジェクトを返すという慣習があるためsuper.clone()
、クローン作成プロセスは最終的にjava.lang.Object
clone()
メソッドに到達します。Cloneable
このメソッドは、まず、対応するオブジェクトがマーカー インターフェイスであるインターフェイスを実装しているかどうかを確認します。そのインスタンスが Cloneable を実装していない場合はCloneNotSupportedException
、オブジェクトのクローン作成中に常に処理する必要があるチェック済み例外である Java をスローします。Java では、クラスがクローン作成をサポートする必要がある場合、次のことを行う必要があります。
A) インターフェイスを実装する必要がありCloneable
ます。B)クラスclone()
からメソッドをオーバーライドする必要があります。Object
[それは奇妙だ。clone()
メソッドはインターフェースにあるはずCloneable
です。]
メソッドに関する Java ドキュメントをclone()
以下に示します (フォーマット済みおよび抜粋)。/* このオブジェクトのコピーを作成して返します。「コピー」の正確な意味は、オブジェクトのクラスによって異なります。一般的な意図は、任意のオブジェクトx
について、式: 1)x.clone() != x
が true になり、//複製されたオブジェクトに別のメモリ アドレスが割り当てられることを保証することです。2)x.clone().getClass() == x.getClass()
は true になりますが、これらは絶対的な要件ではありません。//元のオブジェクトと複製されたオブジェクトは同じクラス型を持つ必要がありますが、必須ではありません。3)x.clone().equals(x)
真になります。これは絶対的な要件ではありません。//元のオブジェクトと複製されたオブジェクトはequals()
メソッドを使用して等しくなければなりませんが、必須ではありません。*/
例を見てみましょう:
public class MyClone {
int x;
public static void main(String[] args) throws
CloneNotSupportedException {
MyClone c = new MyClone();
MyClone a = (MyClone) c.clone(); // Type-cast is required
}
}
はクラスclone()
の一部であり、インターフェースを実装しないため、独自のクラスがインターフェースを実装しない場合、JVM はこのクラスがクローン作成に適していることを認識しないため、出力されます。Object
Object
Cloneable
Cloneable
CloneNotSupportedException
と言うとき、可能なことは 2 つだけですMyClone a = (MyClone) c.clone();
。
どちらかが複製されたオブジェクトを返します。
または、スローしCloneNotSupportedException
ます。
オブジェクトのクローンを作成するときにクラスに実装することが必須ではないことは明らかであるためclone()
、そうしない場合、クラスのclone()
メソッドObject
は保護されていると宣言されます — 同じパッケージのサブクラスとメンバーのみが呼び出すことができclone()
ますオブジェクト。それを変更したい場合は、オーバーライドして公開する必要があります。
clone()
メソッド呼び出し前のチェック:
if(c instanceof Cloneable) {
MyClone a = (MyClone) c.clone();
}
注: gets が呼び出されたときに、コンストラクターは呼び出されませんclone()
。そのクラスのすべてのメンバー変数を適切に設定するのは私たちの責任です。
実装:
Room.java
public class Room {
private String roomSize;
public Room(String roomSize){
this.roomSize = roomSize;
}
//Any Getters-Setters go here
}
Flat.java
public class Flat implements Cloneable {
private String flatNumber;
private Room room;
public Flat(String size,Room room){
this.size = size;
this.room = room;
}
public Object clone() {
try {
return (Flat)super.clone();
}
catch (CloneNotSupportedException e) {
System.out.println("CloneNotSupportedException comes out : "
+e.getMessage());
}
}
//Any Getters-Setters go here
}
Main.java
public class Main {
public static void main(String[] args) {
Room room = new Room("40 X 40");
Flat flat1 = new Flat(403 , room);
Flat flat2 = (Flat)flat1.clone();
}
}
ここsuper.clone()
は内部で呼び出されていclone()
ます。ご存じのとおり、clone()
は で宣言されObject
ているため、すべての Java オブジェクトに継承されます。呼び出しsuper.clone()
により、スーパークラスのフィールドがコピーされ、フィールドのビットごとのコピーが作成されます。これは浅いコピーとして知られています。つまり、をFlat
使用してコピーするclone()
と、フィールドflatNumber
はそれぞれの値でコピーされますが、部屋は参照によってコピーされます — ビットごとにメモリアドレスがコピーされます。
元のオブジェクトの部屋に加えた変更は、複製されたオブジェクトに反映され、その逆も同様です。これを解決するには、ディープコピーが必要です。ここで、クラスを変更し、インターフェイスとメソッドをRoom
実装してから、オブジェクトのメソッド内でオブジェクトのメソッドを呼び出す必要があります。Cloneable
clone()
clone()
Room
clone()
Flat
新しい実装
Room.java
public class Room {
private String roomSize;
public Room(String roomSize){
this.roomSize = roomSize;
}
public Object clone() {
try {
return (Room)super.clone();
}
catch (CloneNotSupportedException e) {
System.out.println("CloneNotSupportedException comes out : "
+e.getMessage());
}
}
//Any Getters-Setters go here
}
Flat.java
public class Flat implements Cloneable {
private String flatNumber;
private Room room;
public Flat(String size,Room room){
this.size = size;
this.room = room;
}
public Object clone() {
Flat flat = null;
try {
flat = (Flat)super.clone();
}
catch (CloneNotSupportedException e) {
System.out.println("CloneNotSupportedException comes out : "
+e.getMessage());
}
flat.room = (Room) room.clone();
return flat;
}
//Any Getters-Setters go here
}
Main.java
public class Main {
public static void main(String[] args) {
Room room = new Room("40 X 40");
Flat flat1 = new Flat(403, room);
Flat flat2 = (Flat)flat1.clone();
}
}
これにより、クローン作成とその実装についての理解が深まることを願っています。
http://interviewguess.blogspot.in/2017/02/how-does-clone-method-work.htmlに感謝します