ستناقش هذه المقالة القضايا الأربعة التالية
1. واجهة جافا المستنسخة تنفذ نسخة عميقة
2. تسلسل جافا ينفذ نسخة عميقة
3. أسرع نسخة من المكتبة العميقة تحليل رمز المصدر استنساخ المكتبة
4. مقارنة سرعات عدة أساليب النسخ
لن أتحدث عن مفهوم النسخة العميقة في هذه المقالة. تنفيذ نسخة عميقة في C ++. بشكل عام ، الزائد على عامل التعيين "=" لتنفيذ نسخة عميقة بين الكائنات من نفس الفئة. لذلك ، من الطبيعي أنه في Java ، يمكننا أيضًا تحديد وظيفة نسخ لتعيين كل خاصية للكائن داخل الوظيفة. هذه الطريقة بسيطة وطبيعية ، ولكن هناك مشكلة قاتلة: إذا تم إضافة سمة جديدة تتطلب نسخة عميقة إلى الفصل ، يجب أيضًا تعديل وظيفة النسخ المقابلة. هذه الطريقة تجلب إزعاجًا كبيرًا لتوسيع الفصل. كيفية حل هذه المشكلة ، دعونا نلقي نظرة على طريقة تنفيذ الفصول 1 و 2 و 3 واختبار السرعة للمادة 4.
1. واجهة جافا المستنسخة تنفذ نسخة عميقة <br /> بهذه الطريقة ، يحتاج الفصل إلى تنفيذ وظيفة استنساخ الواجهة القابلة للاتصال ، والاتصال super.clone في وظيفة الاستنساخ. هذه النسخة العميقة من الطريقة تجلب أيضًا مشكلة أخرى. إذا كانت هناك كائنات من الفئات الأخرى كخصائص في الفصل ، فيجب أن يتم تحميل الفئات الأخرى أيضًا وتنفيذها في الواجهة المستنسخة. هنا مثال. في المثال التالي ، يحتوي Compenshdo على كائنات SimpleDo. لتنفيذ نسخة Deep Complexdo ، تحتاج أولاً إلى تنفيذ واجهة استنساخ Simpledo:
الطبقة العامة simpledo تنفذ استنساخ ، قابلة للتسلسل {private int x = 1 ؛ سلسلة خاصة s = "simpledo" ؛ Override محمية كائن clone () يلقي clonenotsupportedException {simpledo newClass = (simpledo) super.clone () ؛ إرجاع Newclass ؛ }} الفئة العامة compensdo تنفذ استنساخ ، قابلة للتسلسل {private int x = 1 ؛ سلسلة خاصة s = "مجمع" ؛ عدد صحيح خاص A = 123 ؛ عدد صحيح خاص B = 1234 ؛ عدد صحيح خاص C = 1334455 ؛ سلسلة خاصة S2 = "Hehehe" ؛ سلسلة خاصة s3 = "hahaha" ؛ المعرف الطويل الخاص = 1233245L ؛ arraylist private <SimpleDo> l = new ArrayList <SimpleDo> () ؛ Override Public Object Clone () يلقي clonenotsupportedException {Compenshdo newClass = (CompensDdo) super.clone () ؛ newClass.l = new ArrayList <SimpleDo> () ؛ لـ (simpledo بسيط: this.l) {newclass.l.add ((simpledo) simple.clone ()) ؛ } إرجاع NewClass ؛ }} تجدر الإشارة إلى أن العديد من المقالات تقول أن مشغل المهمة لنوع السلسلة هو نسخة عميقة ، ولكن في الواقع ، فإن أولئك الذين يستخدمون مشغلي المهام في Java هم نسخ ضحلة ، ولكن لماذا يجب أن تقول المقالات ذات الأخطاء الواضحة أن هذه نسخة عميقة؟ أفهم أن سمات السلسلة والنوع هي أنواع أساسية ، والطريقة المقدمة ستعمل كائنات جديدة طالما تم تصميم تغييرات البيانات الداخلية. لذلك ، لن تؤثر عملية السلسلة على الذاكرة التي أشار إليها في الأصل. لذلك ، بشكل عام ، فإن عمليات تعيين الفئات الأساسية مثل السلسلة هي نسخ عميقة.
لهذا السبب ، عند استخدام الربط سلسلة السلسلة ، يجب فتح ذاكرة جديدة ، لذا يوصي الكثير من الأشخاص باستخدام StringBuilder بدلاً من السلسلة للربط ، لأن StringBuilder يعيد فقط إعادة تطبيق ذاكرة أكبر عندما لا يكون نطاق صفيف char المدمج كافيًا (ل jvms الحديثة ، وسيتم ضبط الكود ، وسيتم تحسين السلسلة+في تعليمات مماثلة للاشتراك. للاقتصاص مقابل الربط ، هناك وظيفة أساسية في السلسلة. عند استخدام وظيفة Sundring ، هل مجموعة Char الداخلية للسلسلة الجديدة هي نفس السلسلة الأصلية؟ هذا أكثر إثارة للاهتمام. إذا كنت مهتمًا ، فيمكنك مقارنة والتحقق من تنفيذ JDK1.6 و JKD1.7.
2. تسلسل جافا ينفذ نسخة عميقة
يتمثل مبدأ هذه الطريقة في استخدام تسلسل Java لتسلسل كائن في دفق بايت ثنائي ، ثم تخلص من القيمة وتعيينها إلى كائن. مثال رمز:
كائن عام seircopy (كائن src) {try {bytearrayoutputStream byteout = new bytearrayoutputstream () ؛ ObjectOutputStream out = new ObjectOutputStream (byteout) ؛ Out.WriteObject (SRC) ؛ bytearrayinputStream bytein = new ByteArrayInputStream (byteout.tobytearray ()) ؛ ObjectInputStream في = new ObjectInputStream (bytein) ؛ كائن القدر = in.ReadObject () ؛ إعادة القدر } catch (استثناء e) {// القيام ببعض معالج الخطأ إرجاع null ؛ }} بالطبع ، يمكنك أيضًا استخدام JSON والمكتبات التسلسلية الأخرى لإكمال التسلسل. تتجنب هذه الطريقة بشكل فعال أوجه القصور التي يمكن توسيعها لواجهة Cloneabl. يمكن أن تكون الوظيفة مناسبة بشكل أساسي لجميع الفئات. العيب هو أنه نسخة ذاكرة نسبية. يتطلب التسلسل أولاً تحويل الكائن إلى دفق بايت ثنائي ، ثم تخلص من إعادة توصيل دفق البايت الثنائي إلى قطعة من ذاكرة الكائن ، وهو بطيء نسبيًا.
3. أسرع نسخة من المكتبة العميقة تحليل رمز المصدر استنساخ المكتبة
في رمز المصدر ، يكون منطق المعالجة الأساسية في فئة Cloner.
هناك رابطان متكرران:
في (1) ، يكمل FastClone الكائنات الموروثة من فئة واجهة Ifastclone ، أي أنها جميعها نسخ من عمليات التجميع ؛
في (2) ، يكمل CloneObject عملية الحصول على كل خاصية للكائن العادي من خلال آلية الانعكاس ، ثم تعيين قيم لخصائص الكائن الذي تم إنشاؤه حديثًا باستخدام Objenesis.
هذه الطريقة قابلة للتمديد للغاية. لا يمكنك فقط الاعتماد على الكود الحالي لإكمال النسخ العميق ، ولكن يمكنك أيضًا تحديد بعض أساليب وأنواع الاستنساخ التي لا تتطلب الاستنساخ ، وهو مرن للغاية.
4. مقارنة سرعات عدة أساليب النسخ
يمكن استخدام الأوضاع الثلاثة أعلاه لإكمال النسخ العميق ، وأسرع طريقة نسخ هي ما نهتم به.
أولاً ، اختبر الرمز:
public void testclonecomplex () يلقي clonenotsupportedException {Final int copyCount = 1 ؛ قائمة <ColedCdo> ComplexDolist = new ArrayList <ColedCdo> (CopyCount * 3) ؛ مجمع Complexdo النهائي = New ComplexDo () ؛ // حساب المكتبة المكونة من جوانب طويلة = System.CurrentTimeMillis () ؛ لـ (int i = 0 ؛ i <colorcount ؛ ++ i) {Final Complexdo deepclone = clner.deepclone (complex) ؛ ComplexDolist.add (DeepClone) ؛ } نهاية طويلة = system.currentTimeMillis () ؛ System.out.println ("Time Cost Deepclone =" + (end-start)) ؛ // استدعاء وظيفة الاستنساخ التي تنفذها الواجهة المستنسخة start = system.currentTimeMillis () ؛ لـ (int i = 0 ؛ i <colorcount ؛ ++ i) {Final Compensydo interfaceClone = (Complexdo) complex.clone () ؛ complexdolist.add (interfaceClone) ؛ } end = system.currentTimeMillis () ؛ system.out.println ("interfaceClone Cost Time =" + (end-start)) ؛ // تسلسل وفرس إنشاء كائن جديد start = system.currentTimeMillis () ؛ لـ (int i = 0 ؛ i <colorcount ؛ ++ i) {Final Complexdo seirclone = seircopy (complex) ؛ complexdolist.add (seirclone) ؛ } end = system.currentTimeMillis () ؛ System.out.println ("Seirclone Cost Time =" + (end-start)) ؛ }وحدة نتائج التشغيل هي مللي ثانية (يتم تجاهل هذه البيانات ولا تحسب النقاط الساخنة Java و GCs المحتملة).
من هذا الجدول ، يمكننا استخلاص الاستنتاج:
1. نسخ الواجهة المستنسخة هو الأسرع ، لأنه لا يتضمن سوى نسخ للذاكرة ، ولكن إذا كانت السمات المعنية كائنات أكثر شيوعًا ، فمن الصعب الكتابة بعض الشيء.
2. نسخة التسلسل/إزالة التسلسل هي أبطأ
3. باستخدام مكتبة الاستنساخ ، فإن نسخ آلية العودية والانعكاس أبطأ من تطبيق الواجهة المستنسخة ، ولكنه أسرع من طريقة التسلسل.
ما سبق هو كل شيء عن هذا المقال ، آمل أن يكون مفيدًا لتعلم الجميع.