تعد النسخة العميقة (النسخة العميقة) والنسخة الضحلة (النسخة الضحلة) مفهومين شائعين نسبيًا، خاصة في لغة C++ إذا لم تفهمهما، فستواجه مشاكل عند الحذف، ولكن لحسن الحظ نستخدم Java هنا. على الرغم من أن Java تدير إعادة تدوير الكائنات تلقائيًا، إلا أنه لا يزال يتعين علينا إيلاء اهتمام كافٍ للنسخ العميق (النسخ العميق) والنسخ الضحل (النسخ الضحل)، لأن هذين المفهومين غالبًا ما يسببان لنا الكثير من الارتباك.
تعني النسخة الضحلة أنه عند نسخ كائن، يتم نسخ الكائن نفسه فقط (بما في ذلك المتغيرات الأساسية في الكائن)، ولكن لا يتم نسخ الكائن المشار إليه بالمرجع الموجود في الكائن. لا تقوم النسخة العميقة بنسخ الكائن نفسه فحسب، بل تنسخ أيضًا جميع الكائنات المشار إليها بالمراجع الموجودة في الكائن. على سبيل المثال، لتوضيح الأمر: يحتوي الكائن A1 على مرجع إلى B1، ويحتوي B1 على مرجع إلى C1. لا تزال النسخة الضحلة A1 للحصول على A2 تحتوي على مرجع إلى B1، ولا يزال B1 يحتوي على مرجع إلى C1. النسخة العميقة هي تكرار للنسخة العميقة A1 للحصول على A2 الذي يحتوي على مرجع إلى B2 (نسخة من B1)، ويحتوي B2 على مرجع إلى C2 (نسخة من C1).
إذا لم تتم إعادة كتابة طريقة clone()، فإن الكائن الذي تم الحصول عليه عن طريق استدعاء هذه الطريقة هو نسخة ضحلة، دعنا نركز على النسخة العميقة أدناه.
قم بتشغيل البرنامج التالي لإلقاء نظرة على النسخة السطحية:
class Professor0 Implements Cloneable { String name; int age;(String name, int age) { this.name = name; this.age = age } public Object clone() throws CloneNotSupportedException { return super.clone(); class Student0 Implements Cloneable { String name; // كائن ثابت. int age; Professor0 p;// القيم المرجعية للطالب 1 والطالب 2 هي نفسها. Student0(String name, int age, Professor0 p) { this.name = name; this.age = age; this.p = p } public Object clone() { Student0 o = null; .clone(); } Catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } 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; System.out.println("اسم الطالب s1:" + s1.name + "/n اسم أستاذ الطالب s1:" + s1.p.name + ""، + "/n عمر أستاذ الطالب s1" + s1 .p.age);// أستاذ الطالب 1} }
لقد تغير s2، لكن s1 تغير أيضًا، مما يثبت أن p لـ s1 وp لـ s2 يشيران إلى نفس الكائن. هذا ليس هو الحال في احتياجاتنا الفعلية، لذلك نحن بحاجة إلى نسخة عميقة:
class Professor Implements Cloneable { String name; int age; String name, int age) { this.name = this.age = age } public Object clone() { Object o = null; clone(); } Catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } class Student Implements Cloneable { String name; int age; Student(String name, int age, Professor p) { this.name = name; this.p = p } public Object clone() { Student o = null; o = (Student) super.clone(); } Catch (CloneNotSupportedException e) { System.out.println(e.toString()); } op = (Professor) p.clone(); return o; } } public class DeepCopy { public static void main(String args[]) { long t1 = System.currentTimeMillis(); = new Student("zhangsan", 18, p); Student s2 = (Student) s1.clone(); s2.p.name = "lisi"; s2.p.age = 30; System.out.println("name=" + s1.p.name + ""، + "age=" + s1.p.age); // أستاذ الطالب 1 لا يتغير. long t2 = System.currentTimeMillis();
بالطبع، لدينا أيضًا طريقة النسخ العميق، وهي إجراء تسلسل للكائن:
import java.io.*; // التسلسل يستغرق وقتًا طويلاً class Professor2 Implements Serializable { /** * */ Private static Final long serialVersionUID = 1L String name; int age; name = name; this.age = age; } } class Student2 Implements Serializable { /** * */ serialVersionUID طويل ثابت خاص = 1L; كائن ثابت. 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(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(this); // قراءة ByteArrayInputStream من الدفق bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); /** * @param args */ public static void main(String[] args) throwsOptionalDataException, IOException, ClassNotFoundException { long t1 = System.currentTimeMillis(); Professor2 p = new Professor2("wangwu", 50); Student2 s1 = new Student2("zhangsan", 18, p); (); s2.p.name = "lisi"; System.out.println("name=" + s1.p.name + ""، + "age=" + s1.p.age); // أستاذ الطالب 1 لا يتغير. long t2 = System.currentTimeMillis();
ومع ذلك، فإن التسلسل يستغرق وقتًا طويلاً للغاية. في بعض الأطر، يمكننا أن نشعر أنهم غالبًا ما يقومون بتسلسل الكائنات ثم نقلها، الأمر الذي يستغرق الكثير من الوقت.