استثناءات Java هي آلية تناسق توفرها Java لتحديد الأخطاء والرد عليها.
يمكن لآلية استثناء Java فصل رمز معالجة الاستثناءات في البرنامج من رمز العمل العادي ، وتأكد من أن رمز البرنامج أكثر أناقة وتحسين متانة البرنامج. عند استخدام الاستثناءات بشكل فعال ، يمكن للاستثناء أن يجيب بوضوح على هذه الأسئلة الثلاثة: يجيب نوع الاستثناء على "ماذا" والإجابات Trace Trace الاستثناء "حيث" ويجيب معلومات الاستثناء "لماذا".
العديد من الكلمات الرئيسية المستخدمة في آلية استثناء Java: جرب ، اصطياد ، أخيرًا ، رمي ، رميات.
| الكلمات الرئيسية | يوضح |
|---|---|
| يحاول | تستخدم للاستماع. ضع الكود المراد الاستماع إليه (الرمز الذي قد يرمي استثناء) في كتلة TRAW. عندما يحدث استثناء في كتلة بيان المحاولة ، يتم طرح الاستثناء. |
| يمسك | تستخدم للقبض على الاستثناءات. يتم استخدام Catch لالتقاط استثناءات تحدث في كتل بيان المحاولة. |
| أخيراً | أخيرًا ، سيتم تنفيذ كتل البيان دائمًا. يتم استخدامه بشكل أساسي لإعادة تدوير موارد المواد (مثل اتصالات قاعدة البيانات واتصالات الشبكة وملفات القرص) التي تم فتحها في كتل المحاولة. فقط بعد تنفيذ الكتلة أخيرًا ، سيعود أو رمي البيانات في التجربة أو الكتلة. إذا تم استخدام العبارات النهائية مثل الإرجاع أو الرمي ، فلن تقفز مرة أخرى إلى التنفيذ وسوف تتوقف مباشرة. |
| يرمي | تستخدم لرمي الاستثناءات. |
| رميات | تستخدم في توقيعات الطريقة لإعلان الاستثناءات التي قد يتم إلقاؤها بالطريقة. |
الفئة العامة demo1 {public static void main (string [] args) {try {int i = 10/0 ؛ System.out.println ("i ="+i) ؛ } catch (ArithMeticexception e) {system.out.println ("استثناء تم اكتشافه") ؛ System.out.println ("E.GetMessage ():" + E.GetMessage ()) ؛ System.out.println ("E.ToString ():" + E.ToString ()) ؛ System.out.println ("E.PrintStackTrace ():") ؛ E.PrintStackTrace () ؛ }}} نتائج التشغيل:
تم اكتشاف استثناء. getMessage (): / by Zeroe.ToString (): java.lang.arithMeticexception: / by Zeroe.printstacktrace (): java.lang.arithMeticexception: / by zero at demo1.main (demo1.java:6)
وصف النتيجة: هناك عملية مع مقسوم من 0 في كتلة TRAW ، وستقوم العملية بإلقاء java.lang.arithmeticexception. عن طريق الصيد ، يتم القبض على الاستثناء.
لم يتم مراقبة النتائج التي وجدنا أنها system.out.println ("i ="+i) لم يتم تنفيذها. هذا يعني أنه بعد حدوث استثناء في كتلة بيان TRAL ، لن يتم تنفيذ المحتوى المتبقي في كتلة TRAW.
مثال 2: فهم الاستخدام الأساسي أخيرًا
بناءً على "مثال واحد" ، نضيف بيانات أخيرًا.
الفئة العامة demo2 {public static void main (string [] args) {try {int i = 10/0 ؛ System.out.println ("i ="+i) ؛ } catch (ArithMeticexception e) {system.out.println ("استثناء تم اكتشافه") ؛ System.out.println ("E.GetMessage ():" + E.GetMessage ()) ؛ System.out.println ("E.ToString ():" + E.ToString ()) ؛ System.out.println ("E.PrintStackTrace ():") ؛ E.PrintStackTrace () ؛ } أخيرًا {system.out.println ("Run أخيرًا") ؛ }}} نتائج التشغيل:
تم القبض على استثناء. getMessage (): / by Zeroe.ToString (): java.lang.arithmeticexception: / by zeroe.printstacktrace (): java.lang.arithmeticexception: / by Zero في demo2.main (demo2.java:6).
النتائج: تم تنفيذ كتلة البيان أخيرًا.
مثال 3: فهم الاستخدام الأساسي للرميات والرميات
يتم استخدام الرميات لإعلان الاستثناءات التي تم إلقاؤها ، بينما يتم استخدام الرمي لرمي الاستثناءات.
Class MyException يمتد الاستثناء {public myException () {} public myException (String msg) {super (msg) ؛ }} الفئة العامة demo3 {public static void main (string [] args) {try {test () ؛ } catch (myException e) {system.out.println ("catch issulection") ؛ E.PrintStackTrace () ؛ }} اختبار الفراغ الثابت العام () يلقي MyException {try {int i = 10/0 ؛ System.out.println ("i ="+i) ؛ } catch (ArithMeticexception e) {رمي myException جديد ("هذا هو myException") ؛ }}} نتائج التشغيل:
تمسك باستثناء My Evisplement: هذا MyException في Demo3.Test (Demo3.java:24) في Demo3.main (Demo3.java:13)
النتائج: MyException هي فئة فرعية ورثتها من الاستثناء. ArithMeticexception استثناء (مقسم هو 0) يتم إنشاؤه في كتلة بيان المحاولة من Test () ، ويتم اكتشاف الاستثناء في الصيد ؛ ثم يتم إلقاء استثناء MyException. الطريقة الرئيسية () تلتقط MyException التي ألقيت في اختبار ().
إطار استثناء جافا
مخطط الهندسة المعمارية استثناء جافا:
1. رمي
رمي هو فئة فائقة من جميع الأخطاء أو الاستثناءات في لغة جافا.
يحتوي رمي على فئتين فرعيتين: خطأ واستثناء. عادة ما يتم استخدامها للإشارة إلى حدوث خلل.
يحتوي Throwable على لقطات من مؤشر الترابط الذي ينفذ المكدس عند إنشاء مؤشر الترابط الخاص به. يوفر واجهات مثل printstacktrace () للحصول على معلومات مثل بيانات تتبع المكدس.
2. استثناء
الاستثناء والفواصل الفرعية هو شكل من أشكال الرمي التي تشير إلى الشروط التي يريد تطبيق معقول التقاطها.
3. RunTimeException
RunTimeException هي طبقة فائقة قد ترمي استثناءات أثناء التشغيل العادي للجهاز الافتراضي Java.
المترجم لا يتحقق من استثناءات RunTimeException. على سبيل المثال ، عندما يكون المقسوم صفرًا ، يتم إلقاء استثناء ArithMeticeSception. RunTimeException هو فئة فائقة من ArithMeticeSception. عندما يكون للكود مقسومًا للصفر ، يمكن أيضًا تجميعه إذا لم يتم إلقاؤه من خلال إعلان رميات "أو" لا يتم التعامل معه من خلال المحاولة ... الصيد ... ". هذا هو ما نقوله "المترجم لن يتحقق من استثناءات RunTimeException"!
إذا كان الكود ينشئ استثناء RunTimeException ، فيجب تجنبه عن طريق تعديل الكود. على سبيل المثال ، إذا كان المقسوم صفرًا ، فأنت بحاجة إلى تجنب هذا الموقف من خلال الكود!
4. خطأ
مثل الاستثناء ، الخطأ هو أيضا فئة فرعية من رمي. يتم استخدامه للإشارة إلى مشاكل خطيرة لا ينبغي أن يحاول تطبيق معقول التقاطها ، ومعظم هذه الأخطاء هي شروط استثنائية.
مثل RunTimeException ، لن يتحقق المترجم عن خطأ.
تقسم Java بنية الرمي إلى ثلاثة أنواع: استثناء محدد (استثناء محدد) ، استثناء وقت التشغيل (RunTimeException) والخطأ (خطأ).
(1) استثناء وقت التشغيل
التعريف: يسمى RunTimeException ودراساته الفرعية استثناءات وقت التشغيل.
الميزات: لن يتحقق برنامج التحويل البرمجي Java. وهذا يعني أنه عندما يحدث هذا الاستثناء في البرنامج ، إذا لم يتم إلقاؤه من خلال إعلان رميات "أو" لا يتم اكتشافه ببيان المحاولة "، فسيظل يتم تجميعه وإقراره. على سبيل المثال ، استثناء ArithMeticeSception الذي تم إنشاؤه عندما يكون المقسوم صفراً ، فإن استثناء indexoutofboundsexception الذي تم إنشاؤه عندما يكون الصفيف خارج الحدود ، فإن استثناء ConcurrentModificationexception الذي تم إنشاؤه بواسطة آلية الفشل الفشل ، وما إلى ذلك ، كلها استثناءات من وقت التشغيل.
على الرغم من أن برنامج التحويل البرمجي Java لا يتحقق من استثناءات وقت التشغيل ، إلا أنه يمكننا أيضًا إعلانه ورميه من خلال الرميات ، أو التقاطه من خلال المحاولة.
إذا تم إنشاء استثناء وقت التشغيل ، فيجب تجنبه عن طريق تعديل الكود. على سبيل المثال ، إذا كان المقسوم صفرًا ، فأنت بحاجة إلى تجنب هذا الموقف من خلال الكود!
(2) استثناء فحص
التعريف: فئة الاستثناء نفسها ، وغيرها من الفئات الفرعية في الفئات الفرعية للاستثناء باستثناء "استثناء وقت التشغيل" ، تعتبر جميعها استثناءات محددة.
الميزات: سوف يتحقق برنامج التحويل البرمجي Java. يتم الإعلان عن مثل هذه الاستثناءات وإلقاؤها من خلال الرميات أو التقاطها من خلال التجربة ، وإلا لا يمكن تجميعها. على سبيل المثال ، ClonenotsupportedException هو استثناء محدد. عندما يتم استنساخ كائن من خلال واجهة clone () ، ولا تنفذ الفئة المقابلة للكائن الواجهة المستنسخة ، سيتم طرح clonenotsupportedException.
يمكن عادة استرداد الاستثناءات التي يجري فحصها.
(3) خطأ
التعريف: فئة الخطأ والفئات الفرعية.
الميزات: مثل استثناءات وقت التشغيل ، لن يتحقق المترجم عن الأخطاء.
يحدث خطأ عندما لا تكون هناك موارد كافية أو فشل القيود أو غيرها من الشروط التي لا يمكن أن تستمر في تشغيلها بواسطة برامج أخرى. لا يمكن للبرنامج نفسه إصلاح هذه الأخطاء. على سبيل المثال ، VirtualMachineError هو خطأ.
وفقًا لاتفاقية Java ، يجب ألا ننفذ أي فئات فرعية جديدة خطأ!
بالنسبة للهياكل الثلاثة المذكورة أعلاه ، أي واحد يجب أن نرمي استثناء أو خطأ؟ التوصية الواردة في "Java الفعالة" هي: استخدام استثناءات محددة للشروط التي يمكن استردادها ، واستخدام استثناءات وقت التشغيل لأخطاء البرنامج.
العديد من الاقتراحات حول التعامل مع الاستثناء
المادة 1: استخدم الاستثناءات فقط للمواقف غير الطبيعية
التوصية: يجب استخدام الاستثناءات فقط للظروف غير الطبيعية ، ويجب ألا تستخدم أبدًا لتدفقات التحكم العادية.
يتم تقديم التفسير من خلال مقارنة الرموبين أدناه.
الرمز 1
حاول {int i = 0 ؛ بينما (صحيح) {arr [i] = 0 ؛ i ++ ؛ }} catch (indexoutofBoundSexception e) {} code 2for (int i = 0 ؛ i <arr.length ؛ i ++) {arr [i] = 0 ؛} الغرض من كلا الرموبين هو التكرار على صفيف ARR وتعيين قيمة كل عنصر في الصفيف إلى 0. ينتهي الرمز 1 عن طريق الاستثناء ، والذي يبدو من الصعب للغاية فهمه ، ينتهي الرمز 2 حسب حدود الصفيف. يجب أن نتجنب استخدام الرمز 1 لثلاثة أسباب رئيسية:
التصميم الأصلي لآليات الاستثناء مخصص للمواقف غير الطبيعية ، حتى لا يحاول عدد قليل من تطبيقات JVM تحسين أدائها. لذلك ، فإن النفقات العامة لإنشاء الاستثناءات والرمي والقبض على ما يرام.
يمنع وضع الكود في إرجاع Try-Catch من JVM من تنفيذ بعض التحسينات المحددة التي قد تكون لأداء.
لا يؤدي النمط القياسي للعبور المصفوفات إلى فحوصات زائدة عن الحاجة ، وستقوم بعض تطبيقات JVM الحديثة بتحسينها.
في الواقع ، تكون الأوضاع المستندة إلى الاستثناء أبطأ بكثير من الأوضاع القياسية. رمز الاختبار كما يلي:
Class Public Classe1 {private static int [] arr = new int [] {1،2،3،4،5} ؛ حجم ثابت خاص = 10000 ؛ public static void main (string [] args) {long s1 = system.currentTimeMillis () ؛ لـ (int i = 0 ؛ i <size ؛ i ++) endByrange (arr) ؛ long e1 = system.currentTimeMillis () ؛ System.out.println ("endbyrange time:"+(E1-S1)+"MS") ؛ Long S2 = System.CurrentTimeMillis () ؛ لـ (int i = 0 ؛ i <size ؛ i ++) endbyexception (arr) ؛ long e2 = system.currentTimeMillis () ؛ system.out.println ("endbyexception الوقت:"+(E2-S2)+"MS") ؛ } // اجتياز صفيف ARR: private static void endbyexception (int [] arr) {try {int i = 0 ؛ بينما (صحيح) {arr [i] = 0 ؛ i ++ ؛ //system.out.println("endbyrange: arr ["+i+"] = "+arr [i]) ؛ }} catch (indexoutofBoundSexception e) {}} // نقل صفيف ARR: private static void endbyrange (int [] arr) {for (int i = 0 ؛ i <arr.length ؛ i ++) {arr [i] = 0 ؛ //system.out.println("endbyexception: arr ["+i+"] = "+arr [i]) ؛ }}} نتائج التشغيل:
وقت endbyrange: 8msendbyexception الوقت: 16ms
توضح النتيجة أن سرعة اجتياز الاستثناء أبطأ بكثير من اجتياز صفيف بالطريقة العادية!
المادة 2: استخدم استثناءات محددة للشروط القابلة للاسترداد ، واستخدم استثناءات وقت التشغيل لأخطاء البرنامج.
| غير طبيعي | يوضح |
|---|---|
| استثناء وقت التشغيل | تسمى فئة RunTimeException ودراساتها الفرعية استثناءات وقت التشغيل. |
| استثناء محدد | فئة الاستثناء نفسها ، وكذلك الفئات الفرعية الأخرى في استثناء باستثناء "استثناء وقت التشغيل" كلها استثناءات. |
الفرق هو أن برنامج التحويل البرمجي Java يتحقق من "الاستثناءات المحددة" ولا يتحقق من "استثناءات وقت التشغيل".
وهذا يعني ، بالنسبة للاستثناء الذي تم فحصه ، يتم إعلانه وإلقائه من خلال الرميات ، أو يتم التقاطه من خلال التجربة ، وإلا لا يمكن تجميعه. بالنسبة لاستثناءات وقت التشغيل ، إذا لم يتم إلقاؤها من خلال إعلان رميات "أو" لا يتم اكتشافها ببيان المحاولة "، فسيظل يتم تجميعهم وإقرارهم. بالطبع ، على الرغم من أن برنامج التحويل البرمجي Java لا يتحقق من استثناءات وقت التشغيل ، إلا أنه يمكننا أيضًا شرح الاستثناء من خلال الرميات ، أو التمسك به من خلال المحاولة.
RithMeticexception (على سبيل المثال ، المقسوم هو 0) ، indexoutofBoundSexception (على سبيل المثال ، صفيف خارج الحدود) ، وما إلى ذلك كلها استثناءات وقت التشغيل. لهذا الاستثناء ، يجب أن نتجنب ذلك عن طريق تعديل الرمز. للحصول على استثناء تم فحصه ، يمكن استعادة البرنامج ليتم تشغيله من خلال المعالجة. على سبيل المثال ، لنفترض أنه نظرًا لأن المستخدم لا يقوم بتخزين عدد كاف من المكالمات ، فسوف يفشل عند محاولة إجراء مكالمة على مكالمة مدفوعة ؛ وبالتالي رمي استثناء فحص.
المادة 3: تجنب الاستخدام غير الضروري للاستثناءات المحددة
"الاستثناء الخاضع للرقابة" هو ميزة جيدة لجافا. على عكس رمز الإرجاع ، فإن "الاستثناءات المحددة" تجبر المبرمج على التعامل مع شروط الاستثناء ، مما يحسن بشكل كبير موثوقية البرنامج.
ومع ذلك ، فإن الاستخدام المفرط للاستثناءات المحددة يمكن أن يجعل واجهة برمجة التطبيقات غير مريحة للغاية. إذا قامت الطريقة بإلقاء استثناء واحد أو أكثر من الاستثناءات التي تم فحصها ، فيجب على الشفرة التي تستدعي الطريقة التعامل مع هذه الاستثناءات في واحد أو أكثر من بيانات بيان الصيد ، أو يجب إلقاؤها من خلال إعلان رميات. سواء تم التعامل معها من خلال صيد أو إلقاء إعلانات رميات ، فإنه يضيف عبئًا غير مؤهل للمبرمجين.
يجب استيفاء شرطين لـ "استثناءات محددة": أولاً ، حتى إذا تم استخدام واجهة برمجة التطبيقات بشكل صحيح ، فإنه لا يمكن أن يمنع حدوث شروط الاستثناء. ثانياً ، بمجرد إنشاء استثناء ، يمكن للمبرمجين الذين يستخدمون واجهة برمجة التطبيقات اتخاذ إجراءات مفيدة لمعالجة البرنامج.
المادة 4: حاول استخدام الاستثناءات القياسية
إعادة استخدام الكود تستحق الدعوة ، وهذا قاعدة مشتركة ، والاستثناءات ليست استثناء. هناك العديد من الفوائد لإعادة استخدام الاستثناءات الحالية:
أولاً ، يجعل واجهة برمجة التطبيقات الخاصة بك أسهل في التعلم والاستخدام لأنها تتفق مع التعابير التي أصبح المبرمجون على دراية بها.
ثانياً ، بالنسبة للبرامج التي تستخدم واجهات برمجة التطبيقات هذه ، فهي قابلة للقراءة بشكل أفضل لأنها ليست مليئة باستثناءات غير مألوفة للمبرمجين.
ثالثًا ، كلما كانت فئات الاستثناء أقل ، وأصغر استخدام الذاكرة ، وأصغر الوقت الذي تقضيه في إعادة طباعة هذه الفئات.
غالبًا ما تستخدم العديد من الاستثناءات القياسية Java استثناءات. الجدول التالي:
| غير طبيعي | استخدم المناسبات |
|---|---|
| غير شرعي | قيمة المعلمة غير مناسبة |
| غير شرعي | المعلمات غير مناسبة |
| nullpointerxception | عندما يتم تعطيل فارغ ، تكون قيمة المعلمة فارغة |
| indexoutofboundsexception | يعبر الحدود المترتبة الحدود |
| ConcurrentModificationException | عندما يتم حظر التعديل المتزامن ، يكتشف الكائن التعديل المتزامن |
| UnsupportedOperationException | الأساليب التي لا تدعم طلبات العملاء |
على الرغم من أنها الاستثناءات الأكثر شيوعًا لمكتبات منصة Java حتى الآن ، إلا أنه يمكن أيضًا إعادة استخدام استثناءات أخرى في ظل ظروف الترخيص. على سبيل المثال ، إذا كنت ترغب في تنفيذ كائنات حسابية مثل الأرقام المعقدة أو المصفوفات ، فسيكون من المناسب جدًا إعادة استخدام ArithMeticeSception و NumberFormatexception. إذا تلبي استثناء احتياجاتك ، فلا تتردد في استخدامه ، ولكن يجب عليك التأكد من أن حالة رمي الاستثناء تتوافق مع الشروط الموضحة في الوثائق للاستثناء. يجب أن يعتمد هذا إعادة الاستخدام على دلالات ، وليس على الاسم!
أخيرًا ، تأكد من أنه من الواضح أنه لا توجد قاعدة يجب اتباعها عند اختيار استثناء إعادة الاستخدام. على سبيل المثال ، بالنظر إلى حالة كائن بطاقة ، افترض أن هناك طريقة لعمليات التعامل ، ومعلمة (Holdize) هي عدد البطاقات التي سيتم تقديمها في اليد. لنفترض أن المتصل يمرر قيمة في هذه المعلمة أكبر من العدد المتبقي من البطاقات للسطح بأكمله. بعد ذلك ، يمكن تفسير هذا الموقف على أنه غير شرعي من غيره (قيمة اليدين كبيرة جدًا) أو ككلام غير قانوني (يحتوي كائن البطاقة على عدد قليل جدًا من البطاقات بالنسبة لطلب العميل).
المادة 5: يجب أن يكون الاستثناء الذي تم طرحه مناسبًا للتجريد المقابل
يمكن أن يكون هذا الموقف ساحقًا إذا لم يكن للاستثناء الذي تم إلقاؤه بواسطة الطريقة أي علاقة واضحة بالمهمة التي يؤديها. يحدث هذا غالبًا عندما تمر الطريقة باستثناء تم إلقاؤه بواسطة تجريد منخفض المستوى. عندما يحدث هذا ، فإنه لا يربك فحسب ، بل يخلط أيضًا ، ولكن أيضًا واجهات برمجة التطبيقات عالية المستوى.
لتجنب هذه المشكلة ، يجب أن يلتقط التنفيذ رفيع المستوى الاستثناء منخفض المستوى ورمي استثناء يمكن تقديمه وفقًا للتجريد عالي المستوى. وتسمى هذه الممارسة "ترجمة الاستثناء".
على سبيل المثال ، فإن طريقة مجموعة Java Collection AbstractSextialList GET () هي كما يلي (استنادًا إلى JDK1.7.0_40):
public e get (int index) {try {return listiTerator (index) .next () ؛ } catch (nosuchelementException Exc) {رمي indexoutofboundsexception جديد ("index:"+index) ؛ }}ستعيد ListIratorator (الفهرس) كائن ListIterator. قد يستدعي استدعاء الطريقة التالية () الكائن استثناءً من nosuchelementException. في طريقة GET () ، سيكون رمي استثناء nosuchelementexception مربكًا. لذلك ، get () يلتقط nosuchelementException ويرمي استثناء indexoutofboundsexception. وهذا يعني أنه يعادل تحويل nosuchelementException إلى indexoutofboundsexception استثناء.
المادة 6: يجب توثيق الاستثناء الذي ألقاه كل طريقة
لإعلان الاستثناء الذي تم فحصه بشكل منفصل ، واستخدم علامة @therws من Javadoc لتسجيل الشروط بدقة لكل استثناء يتم طرحه.
إذا كانت العديد من الأساليب في فصل ما هي نفس الاستثناء لنفس السبب ، فمن المقبول القيام بالوثائق لهذا الاستثناء في تعليقات المستند لتلك الفئة ، بدلاً من التوثيق بشكل فردي لكل طريقة.
المادة 7: قم بتضمين رسالة الفشل بالتفصيل
باختصار ، عندما نقوم بتخصيص أو نلقي استثناء ، يجب أن ندرج المعلومات المتعلقة بالفشل.
عندما يفشل البرنامج بسبب استثناء غير معطل ، سيقوم النظام تلقائيًا بطباعة تتبع المكدس للاستثناء. يحتوي على تمثيل سلسلة للاستثناء في مسار المكدس. عادةً ما يحتوي على اسم فئة فئة الاستثناء ، إلى جانب الرسالة التفصيلية التالية.
المادة 8: السعي للحفاظ على الذرة في الفشل
عندما يلقي كائن استثناء ، نتوقع دائمًا أن يبقى الكائن في حالة متوفرة محددة جيدًا. هذا مهم بشكل خاص للاستثناء الذي تم فحصه ، لأن المتصل يتوقع عادةً التعافي من الاستثناء الذي تم فحصه.
بشكل عام ، يجب أن تبقي مكالمة الطريقة الفاشلة الكائن في "حالتها قبل استدعاءها". وتسمى الطرق مع هذه السمات "فشل ذري". يمكن فهم أن الفشل لا يزال يحافظ على الذرة. هناك عدة طرق لكائن للحفاظ على "ذرة فاشلة":
(1) تصميم كائن غير قابل للتطبيق.
(2) بالنسبة للطرق التي تؤدي العمليات على الكائنات القابلة للتغيير ، فإن الطريقة الأكثر شيوعًا للحصول على "ذرة فاشلة" هي التحقق من صحة المعلمات قبل إجراء العملية. على النحو التالي (طريقة البوب في stack.java):
الكائن العام pop () {if (size == 0) رمي فارغ stackexception () ؛ نتيجة الكائن = عناصر [-الحجم] ؛ عناصر [الحجم] = فارغة ؛ نتيجة العودة ؛} (3) على غرار الطريقة السابقة ، يمكن ضبط معالجة الحساب بحيث يحدث أي فشل محتمل في جزء الحساب قبل تعديل حالة الكائن.
(4) اكتب رمز الاسترداد لشرح الإخفاقات أثناء العملية ولإعادة الكائن إلى الحالة قبل بدء العملية.
(5) قم بإجراء عملية على نسخة مؤقتة من الكائن ، وبعد اكتمال العملية ، انسخ النتيجة في النسخة المؤقتة إلى الكائن الأصلي.
في حين أن "الحفاظ على ذرة كائن فاشلة" هو الهدف المطلوب ، فليس من الممكن دائمًا. على سبيل المثال ، إذا كانت مؤشرات الترابط المتعددة تحاول الوصول إلى كائن في وقت واحد دون آليات التزامن المناسبة ، فقد يترك الكائن في حالة غير متسقة.
حتى في الحالات التي يمكن فيها تحقيق "ذرة فاشلة" ، لا يمكن دائمًا ذلك المتوقع. بالنسبة لبعض العمليات ، يمكن أن تزيد بشكل كبير من النفقات العامة أو التعقيد.
القاعدة العامة هي: كجزء من مواصفات الطريقة ، لا ينبغي لأي استثناء تغيير حالة الكائن قبل استدعاء الطريقة. إذا تم انتهاك هذه القاعدة ، فيجب أن تشير وثائق API بوضوح إلى الحالة التي سيكون فيها الكائن.
المادة 9: لا تتجاهل الاستثناءات
عندما يعلن مصمم واجهة برمجة التطبيقات أن الطريقة ستعلق استثناء ، فإنهم يحاولون توضيح شيء ما. لذا ، من فضلك لا تتجاهلها! الرمز لتجاهل الاستثناءات هو كما يلي:
جرب {...} catch (someException e) {} ستجعل كتلة الصيد الفارغة الاستثناء فشل في تحقيق هدفها المستحق. الغرض من الاستثناء هو إجبارك على التعامل مع الظروف غير الطبيعية. إن تجاهل الاستثناء يشبه تجاهل إشارة إنذار الحريق - إذا تم إيقاف إشارة إنذار الحريق ، فلن يرى أحد إشارة إنذار الحريق عند حدوث النار الحقيقية. لذلك ، على الأقل يجب أن تحتوي كتلة الصيد على وصف يفسر سبب كونه مناسبًا لتجاهل هذا الاستثناء.