كيفية التعامل مع استثناءات Java بالطريقة الصحيحة

كيفية التعامل مع استثناءات Java بالطريقة الصحيحة

بصفتك مبتدئًا في البرمجة ، فإن مفهوم معالجة الاستثناء يمكن أن يكون من الصعب لف رأسك حولها. لا يعني ذلك أن المفهوم نفسه صعب ، ولكن المصطلحات يمكن أن تجعله يبدو أكثر تقدمًا مما هو عليه. وهي ميزة قوية لدرجة أنها عرضة لسوء الاستخدام وإساءة الاستخدام.





في هذه المقالة ، ستتعرف على الاستثناءات وسبب أهميتها وكيفية استخدامها والأخطاء الشائعة التي يجب تجنبها. تتمتع معظم اللغات الحديثة بنوع من التعامل مع الاستثناءات ، لذلك إذا انتقلت من Java ، يمكنك أخذ معظم هذه النصائح معك.





فهم استثناءات Java

في جافا ، يوجد ملف استثناء هو كائن يشير إلى حدوث شيء غير طبيعي (أو 'استثنائي') أثناء تشغيل التطبيق الخاص بك. هذه الاستثناءات القيت ، وهو ما يعني أساسًا إنشاء كائن استثناء (على غرار كيفية 'ظهور' الأخطاء).





الجمال هو ما تستطيع يمسك تم طرح الاستثناءات ، والتي تتيح لك التعامل مع الحالة غير الطبيعية والسماح لتطبيقك بالاستمرار في العمل كما لو لم يحدث خطأ. على سبيل المثال ، في حين أن المؤشر الفارغ في C قد يؤدي إلى تعطل تطبيقك ، فإن Java تتيح لك الرمي والتقاط

NullPointerException

قبل أن يكون للمتغير الفارغ فرصة للتسبب في حدوث عطل.



تذكر أن الاستثناء هو مجرد كائن ، ولكن له خاصية مهمة واحدة: يجب أن يمتد من

Exception

فئة أو أي فئة فرعية من





Exception

. بينما تحتوي Java على جميع أنواع الاستثناءات المضمنة ، يمكنك أيضًا إنشاء استثناءات خاصة بك إذا كنت ترغب في ذلك. قليلا من ال استثناءات Java الأكثر شيوعًا يشمل:

  • NullPointerException
  • NumberFormatException
  • IllegalArgumentException
  • RuntimeException
  • IllegalStateException

إذن ماذا يحدث عندما تطرح استثناء؟





أولاً ، تبحث Java في الطريقة الفورية لمعرفة ما إذا كان هناك رمز يتعامل مع نوع الاستثناء الذي قمت بإلقائه. إذا لم يكن المعالج موجودًا ، فإنه يبحث في الطريقة التي تسمى الطريقة الحالية لمعرفة ما إذا كان هناك مقبض. إذا لم يكن كذلك ، فإنه يبحث في الطريقة التي تسمى الذي - التي الطريقة ، ثم الطريقة التالية ، إلخ. إذا لم يتم اكتشاف الاستثناء ، يقوم التطبيق بطباعة تتبع المكدس ثم يتعطل. (في الواقع ، الأمر أكثر دقة من مجرد الانهيار ، ولكن هذا موضوع متقدم يتجاوز نطاق هذا المقال.)

إلى تتبع المكدس هي قائمة بكل الطرق التي اجتازتها Java أثناء البحث عن معالج استثناء. إليك ما يبدو عليه تتبع المكدس:

Exception in thread 'main' java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

يمكننا استخلاص الكثير من هذا. أولاً ، كان الاستثناء الذي تم طرحه هو ملف

NullPointerException

. حدث ذلك في

getTitle()

طريقة في السطر 16 من Book.java. تم استدعاء هذه الطريقة من

getBookTitles()

على السطر 25 من Author.java. الذي - التي تم استدعاء الطريقة من

main()

على السطر 14 من Bootstrap.java. كما ترى ، فإن معرفة كل هذا يجعل تصحيح الأخطاء أسهل.

ولكن مرة أخرى ، الفائدة الحقيقية للاستثناءات هي أنه يمكنك 'معالجة' الحالة غير الطبيعية من خلال اكتشاف الاستثناء ، وتعيين الأمور في نصابها الصحيح ، واستئناف التطبيق دون تعطل.

استخدام استثناءات Java في التعليمات البرمجية

لنفترض أن لديك

someMethod()

يأخذ عددًا صحيحًا وينفذ بعض المنطق الذي يمكن أن ينكسر إذا كان العدد الصحيح أقل من 0 أو أكبر من 100. قد يكون هذا مكانًا جيدًا لطرح استثناء:

كيفية ss snaps دون علمهم
public void someMethod(int value) {
if (value 100) {
throw new
IllegalArgumentException

للقبض على هذا الاستثناء ، عليك أن تذهب إلى حيث

someMethod()

يسمى واستخدام كتلة محاولة الصيد :

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
}
// ...
}

كل شيء داخل محاولة سيتم تنفيذ block بالترتيب حتى يتم طرح استثناء. بمجرد طرح استثناء ، يتم تخطي جميع العبارات اللاحقة وينتقل منطق التطبيق فورًا إلى ملف يمسك منع.

في مثالنا ، ندخل كتلة try ونتصل على الفور

someMethod()

. نظرًا لأن 200 ليس بين 0 و 100 ، فإن

IllegalArgumentException

هذا خطئ. هذا ينهي على الفور تنفيذ

someMethod()

، يتخطى بقية المنطق في كتلة try (

someOtherMethod()

لا يُستدعى أبدًا) ، ويستأنف التنفيذ داخل كتلة catch.

ماذا سيحدث لو اتصلنا

someMethod(50)

في حين أن؟ ال

IllegalArgumentException

لن يتم إلقاؤها.

someMethod()

ستنفذ كالمعتاد. سيتم تنفيذ كتلة المحاولة كالمعتاد ، استدعاء

someOtherMethod()

عندما يكتمل someMethod (). متي

someOtherMethod()

ينتهي ، سيتم تخطي كتلة الصيد و

callingMethod()

سيستمر.

لاحظ أنه يمكن أن يكون لديك عدة كتل catch لكل مجموعة محاولة:

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
} catch (NullPointerException e) {
// handle the exception in here
}
// ...
}

لاحظ أيضًا أنه اختياري أخيرا الكتلة موجودة أيضًا:

public void method() {
try {
// ...
} catch (Exception e) {
// ...
} finally {
// ...
}
}

الكود الموجود داخل الكتلة النهائية هو دائما أعدم مهما حدث. إذا كان لديك تعليمة عودة في كتلة try ، فسيتم تنفيذ الكتلة النهائية قبل العودة من الطريقة. إذا قمت بطرح استثناء آخر في كتلة catch ، فسيتم تنفيذ الكتلة النهائية قبل طرح الاستثناء.

يجب عليك استخدام الكتلة النهائية عندما يكون لديك أشياء تحتاج إلى التنظيف قبل انتهاء الطريقة. على سبيل المثال ، إذا فتحت ملفًا في كتلة try وأطلقت استثناءً لاحقًا ، فإن الكتلة الأخيرة تتيح لك إغلاق الملف قبل مغادرة الطريقة.

لاحظ أنه يمكنك الحصول على كتلة أخيرة بدون كتلة catch:

public void method() {
try {
// ...
} finally {
// ...
}
}

يتيح لك هذا إجراء أي عملية تنظيف ضرورية مع السماح للاستثناءات التي تم طرحها بنشر مكدس استدعاء الطريقة (أي أنك لا تريد معالجة الاستثناء هنا ولكنك لا تزال بحاجة إلى التنظيف أولاً).

تم الفحص مقابل الاستثناءات التي لم يتم التحقق منها في Java

على عكس معظم اللغات ، تميز Java بين فحص الاستثناءات و استثناءات لم يتم التحقق منها (على سبيل المثال ، يحتوي C # فقط على استثناءات لم يتم التحقق منها). استثناء محدد يجب يتم اكتشافها في الطريقة التي يتم فيها طرح الاستثناء وإلا فلن يتم تجميع الشفرة.

لإنشاء استثناء محدد ، قم بالتمديد من

Exception

. لإنشاء استثناء غير محدد ، قم بالتمديد من

RuntimeException

.

يجب أن تشير أي طريقة تفرض استثناءً محددًا إلى هذا في توقيع الطريقة باستخدام رميات كلمة رئيسية. منذ أن بنيت في جافا

IOException

هو استثناء محدد ، فلن يتم ترجمة الكود التالي:

public void wontCompile() {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

يجب أن تعلن أولاً أنه يطرح استثناءً محددًا:

public void willCompile() throws IOException {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

لاحظ أنه يمكن التصريح عن طريقة ما على أنها تطرح استثناءً ولكن لا تطرح استثناءً في الواقع. ومع ذلك ، سيظل الاستثناء بحاجة إلى اكتشافه وإلا فلن يتم تجميع الكود.

متى يجب استخدام الاستثناءات المحددة أو غير المحددة؟

تحتوي وثائق Java الرسمية على ملف صفحة على هذا السؤال . إنها تلخص الاختلاف بقاعدة موجزة: 'إذا كان من الممكن بشكل معقول توقع تعافي العميل من استثناء ، اجعله استثناءًا محددًا. إذا لم يتمكن العميل من فعل أي شيء للتعافي من الاستثناء ، فاجعله استثناءً لم يتم التحقق منه.

لكن هذا المبدأ التوجيهي قد يكون عفا عليه الزمن. من ناحية أخرى ، تؤدي الاستثناءات المحددة إلى كود أكثر قوة. من ناحية أخرى ، لم تتحقق أي لغة أخرى من الاستثناءات بنفس طريقة Java ، والتي تُظهر شيئين: الأول ، الميزة ليست مفيدة بما يكفي للغات الأخرى لسرقتها ، والثاني ، يمكنك العيش بدونها تمامًا. بالإضافة إلى ذلك ، لا تعمل الاستثناءات المحددة بشكل جيد مع تعبيرات lambda المقدمة في Java 8.

إرشادات لاستخدام استثناءات Java

الاستثناءات مفيدة ولكن من السهل إساءة استخدامها وإساءة استخدامها. إليك بعض النصائح وأفضل الممارسات لمساعدتك على تجنب إحداث فوضى بها.

  • تفضل استثناءات محددة للاستثناءات العامة. استخدم NumberFormatException أكثر من IllegalArgumentException عند الإمكان ، استخدم IllegalArgumentException أكثر من RuntimeException عندما يكون ذلك ممكنا.
  • لا تلتقط Throwable ! ال Exception يمتد الفصل فعليًا Throwable ، وتعمل كتلة catch فعليًا مع Throwable أو أي فئة تتسع للرمي. ومع ذلك ، فإن Error يمتد الفصل أيضًا Throwable ، ولا تريد أبدًا التقاط Error بسبب Error تشير s إلى مشكلات خطيرة لا يمكن إصلاحها.
  • لا تلتقط Exception ! InterruptedException يمتد Exception ، أي كتلة تلتقط Exception سيصطاد أيضًا InterruptedException ، وهذا استثناء مهم للغاية لا تريد العبث به (خاصة في التطبيقات متعددة الخيوط) إلا إذا كنت تعرف ما تفعله. إذا كنت لا تعرف الاستثناء الذي يجب التقاطه بدلاً من ذلك ، ففكر في عدم التقاط أي شيء.
  • استخدم الرسائل الوصفية لتسهيل التصحيح. عند طرح استثناء ، يمكنك توفير String الرسالة كحجة. يمكن الوصول إلى هذه الرسالة في كتلة catch باستخدام Exception.getMessage() الطريقة ، ولكن إذا لم يتم اكتشاف الاستثناء مطلقًا ، فستظهر الرسالة أيضًا كجزء من تتبع المكدس.
  • حاول ألا تلتقط وتجاهل الاستثناءات. للتغلب على إزعاج الاستثناءات المحددة ، سيقوم الكثير من المبرمجين المبتدئين والكسالى بإعداد كتلة catch لكنهم يتركونها فارغة. سيء! تعامل دائمًا مع الأمر بأمان ، ولكن إذا لم تتمكن من ذلك ، فقم على الأقل بطباعة تتبع مكدس حتى تعرف أن الاستثناء قد تم طرحه. يمكنك القيام بذلك باستخدام Exception.printStackTrace() طريقة.
  • احذر من الإفراط في استخدام الاستثناءات. عندما يكون لديك مطرقة ، كل شيء يبدو وكأنه مسمار. عندما تتعرف على الاستثناءات لأول مرة ، قد تشعر بأنك مضطر لتحويل كل شيء إلى استثناء ... لدرجة أن معظم تدفق التحكم في تطبيقك ينحصر في معالجة الاستثناءات. تذكر أن الاستثناءات مخصصة للحوادث 'الاستثنائية'!

الآن يجب أن تكون مرتاحًا بما يكفي مع الاستثناءات لفهم ماهيتها ، ولماذا يتم استخدامها ، وكيفية دمجها في التعليمات البرمجية الخاصة بك. إذا لم تفهم المفهوم تمامًا ، فلا بأس بذلك! لقد استغرق الأمر مني بعض الوقت حتى 'نقر' في رأسي ، لذلك لا تشعر أنك بحاجة إلى التعجيل بها. خذ وقتك.

هل لديك أي أسئلة؟ هل تعرف أي نصائح أخرى فاتتها متعلقة بالاستثناءات؟ انشرهم في التعليق التالي!

يشارك يشارك سقسقة بريد الالكتروني كيفية إنشاء مخطط تدفق البيانات لتصور بيانات أي مشروع

تساعدك مخططات تدفق البيانات (DFD) لأي عملية على فهم كيفية تدفق البيانات من المصدر إلى الوجهة. إليك كيفية إنشائه!

اقرأ التالي
مواضيع ذات صلة
  • برمجة
  • جافا
نبذة عن الكاتب جويل لي(تم نشر 1524 مقالة)

جويل لي هو رئيس تحرير MakeUseOf منذ عام 2018. وهو حاصل على بكالوريوس العلوم. في علوم الكمبيوتر وأكثر من تسع سنوات من الخبرة المهنية في الكتابة والتحرير.

كيفية اقتصاص صورة في دائرة
المزيد من Joel Lee

اشترك في نشرتنا الإخبارية

انضم إلى النشرة الإخبارية لدينا للحصول على نصائح تقنية ومراجعات وكتب إلكترونية مجانية وصفقات حصرية!

انقر هنا للاشتراك