ディープ コピー (深いコピー) と浅いコピー (浅いコピー) は、特に C++ 言語では比較的一般的な概念です。これを理解していないと、削除するときに問題が発生します。しかし、幸いなことに、ここでは Java を使用しています。 Java はオブジェクトのリサイクルを自動的に管理しますが、深いコピー (深いコピー) と浅いコピー (浅いコピー) には十分な注意を払う必要があります。これら 2 つの概念は、しばしば多くの混乱を引き起こすためです。
浅いコピーとは、オブジェクトをコピーするときに、オブジェクト自体 (オブジェクト内の基本変数を含む) のみがコピーされ、オブジェクトに含まれる参照が指すオブジェクトはコピーされないことを意味します。ディープ コピーは、オブジェクト自体をコピーするだけでなく、オブジェクトに含まれる参照が指すすべてのオブジェクトもコピーします。たとえば、わかりやすくするために、オブジェクト A1 には B1 への参照が含まれ、B1 には C1 への参照が含まれています。 A2 を取得するために A1 を浅くコピーします。A2 には B1 への参照が含まれており、B1 には C1 への参照が含まれています。ディープ コピーは、A2 を取得するための浅いコピー A1 の再帰です。A2 には B2 (B1 のコピー) への参照が含まれ、B2 には C2 (C1 のコピー) への参照が含まれます。
clone() メソッドが書き換えられていない場合、このメソッドを呼び出して取得されるオブジェクトは浅いコピーになります。以下ではディープ コピーに注目してみましょう。
次のプログラムを実行して、浅いコピーを確認します。
class Professor0 は Cloneable { String name; Professor0(String name, int age) を実装します。 public Object clone() throws CloneNotSupportedException { return super.clone(); } class Student0 は Cloneable { // 定数オブジェクトを実装します。 int age; Professor0 p;//学生 1 と学生 2 の基準値は同じです。 Student0(String name, int age, Professor0 p) { this.name = name; this.age = age; } public Object clone() { o = (Student0) super; .clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()) } } public class ShallowCopy { public static void main(String[] args) { Professor0 p = new Professor0("wangwu", 50); Student0 s1 = new Student0("zhangsan", 18, p); p.name = "lisi"; s2.p.age = 30; s2.name = "z"; System.out.println("学生 s1 の名前:" + s1.name + "/n 学生 s1 の教授の名前:" + s1.p.name + "," + "/n 学生 s1 の教授の年齢" + s1 .p.age);//学生 1 の教授} }
s2 は変更されましたが、s1 も変更されており、s1 の p と s2 の p が同じオブジェクトを指していることがわかります。これは実際のニーズには当てはまらないため、ディープコピーが必要です。
class Professor は Cloneable を実装します。 String name; Professor(String name, int age) { this.name = name; this.age = age; } public Object clone() { Object o = null; clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()) } return o; } クラス Student は Cloneable { 文字列名を実装します。 int 年齢; 学生 (文字列名, int 年齢, 学生 p) { this.name = 名前; this.p = p } public Object clone() { 学生 o = null; o = (学生) super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()) } op = (教授) p.clone(); return o; } } public class DeepCopy { public static void main(String args[]) {long t1 = System.currentTimeMillis(); = 新しい学生("zhangsan", 18, p); 学生 s2 = (学生) s1.clone(); s2.p.name = "lisi"; s2.p.age = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // 学生 1 の教授は変更されません。長い t2 = System.currentTimeMillis();
もちろん、オブジェクトをシリアル化するディープ コピー メソッドもあります。
import java.io.*; //シリアル化には時間がかかります。 class Professor2 は Serializable { /** * */ private static Final long string name, int age; this. name = 名前; this.age = 年齢; } } class Student2 は Serializable { /** * */ private static Final long string name;//定数オブジェクト。 int age; Professor2 p;//生徒 1 と生徒 2 の基準値は同じです。 Student2(String name, int age, Professor2 p) { this.name = name; this.age = age; this.p = p } public Object deepClone() throws IOException, OptionalDataException, ClassNotFoundException { // オブジェクトをストリーム ByteArrayOutputStream bo = new ByteArrayOutputStream(); oo = new ObjectOutputStream(bo); oo.writeObject(this); // ストリームから ByteArrayInputStream を読み取ります bi = new ByteArrayInputStream(bo.toByteArray()) oi = new ObjectInputStream(bi); public class DeepCopy2 { /** * @param args */ public static void main(String[] args) throws OptionalDataException, IOException, ClassNotFoundException {long t1 = System.currentTimeMillis(); Professor2 p = new Student2("wangwu", 50); Student2 s2 = (Student2) s1.deepClone; (); s2.p.name = "リシ"; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // 学生 1 の教授は変更されません。長い t2 = System.currentTimeMillis();
ただし、シリアル化には非常に時間がかかり、フレームワークによってはオブジェクトをシリアル化してから転送することが多く、時間がかかることが多いと感じます。