try و catch و finally
try و catch و finally
في الدرس السابق تعلّمت ما هي الاستثناءات ولماذا توجد. حان الآن وقت تعلّم الكلمات المفتاحية الثلاث التي تسمح لك بـمعالجة هذه الاستثناءات: try وcatch وfinally. معًا توفّر لك طريقة منظّمة لتغليف الكود الخطر والتعافي من المشكلات وضمان التنظيف — بغضّ النظر عمّا يحدث.
لماذا نغلّف الكود أصلًا؟
بدون معالجة الاستثناءات، أي حدث غير متوقّع — ملف غير موجود، مهلة شبكة، إدخال خاطئ من المستخدم — يُعطّل برنامجك بالكامل. بكتلة try ترسم حدًّا واقيًا حول الكود الخطر. إذا حدث خطأ داخل هذا الحد، يبحث Java عن كتلة catch مناسبة بدلًا من التوقّف.
كتلة try
تحتوي كتلة try على التعليمات التي قد تُطلق استثناءً. لا يمكنها الوقوف وحدها — يجب أن يتبعها على الأقل كتلة catch واحدة أو كتلة finally أو كلتاهما.
هنا 10 / 0 يُطلق استثناء ArithmeticException. لأن التعليمة داخل كتلة try، ينقل Java التحكّم إلى كتلة catch المناسبة بدلًا من تعطيل التطبيق.
كتلة catch
تُعلن كتلة catch عن نوع الاستثناء الذي تعالجه وتمنحه اسمًا محليًا (باتّفاق e أو ex). يمكنك فقط اصطياد الاستثناءات التي تطابق النوع المُطلَق تمامًا أو نوعًا أب في التسلسل الهرمي (المزيد في الدرس الثالث).
لاحظ أن السطر System.out.println("تمّ التحليل: " + number) لن يُنفَّذ أبدًا عند فشل التحليل. ينتقل Java مباشرةً من نقطة الفشل إلى كتلة catch، ثم يكمل بعد منشأة try-catch بأكملها.
e كائن. يحمل معلومات عمّا حدث. أكثر الدوال فائدة هي e.getMessage() (وصف مختصر) وe.toString() (النوع + الرسالة). لأغراض التصحيح أثناء التطوير، تطبع e.printStackTrace() سلسلة الاستدعاء الكاملة.
كتل catch متعدّدة
يمكن أن تتبع كتلة try واحدة عدّة كتل catch، كلٌّ منها يعالج نوعًا مختلفًا من الاستثناءات. يتحقّق Java منها بالترتيب من الأعلى ويُنفّذ أول واحدة تتطابق.
FileNotFoundException هي فئة ابن من IOException. إذا وضعت كتلة IOException أولًا ستستوعب FileNotFoundException أيضًا، وسيُشير المُصرِّف إلى أن الكتلة الثانية لن تُنفَّذ أبدًا. رتّب دائمًا كتل catch من الأكثر تحديدًا إلى الأكثر عمومية.
كتلة finally
تعمل كتلة finally بغضّ النظر عمّا يحدث — سواء نجحت كتلة try، أو اصطِيد استثناء، أو حتى إذا أُطلق استثناء ولم يُصطَد. إنها المكان المناسب لكود التنظيف: إغلاق اتصال، تحرير قفل، مسح مخزن مؤقت.
حتى لو أطلق new FileReader("config.txt") استثناءً وعملت كتلة catch، تُنفَّذ كتلة finally بعدها. هذا الضمان هو ما يجعل finally موثوقة لإدارة الموارد.
AutoCloseable (مشمول في الدرس 8). في الوقت الحالي، فهم النهج اليدوي بـ finally يعلّمك تمامًا ما يفعله try-with-resources تلقائيًا.
تدفّق التحكّم باختصار
- إذا لم يُطلَق استثناء: تعمل كتلة
tryكاملةً، وتُتجاهلcatch، وتعملfinally. - إذا أُطلق استثناء اصطِيد: تتوقّف
tryعند نقطة الإطلاق، وتعمل كتلةcatchالمناسبة، وتعملfinally. - إذا أُطلق استثناء لم يُصطَد: تتوقّف
try، وتُتجاوَز جميع كتلcatch، وتعملfinallyمع ذلك، ثم يتصاعد الاستثناء في مكدّس الاستدعاء.
finally على تعليمة return، فإنها تتجاهل بصمت أي استثناء كان في طور التصاعد. هذه واحدة من أكثر الأخطاء إرباكًا في Java. أبقِ كتل finally مركّزة على التنظيف لا على إرجاع القيم.
مثال متكامل
إليك دالة صغيرة تقرأ عددًا صحيحًا من نص وتجمع الكتل الثلاث وتُظهر تدفّق التحكّم بوضوح:
الخلاصة
استخدم try لتمييز الكود الذي قد يفشل، وcatch لمعالجة المشكلات المحدّدة بأناقة، وfinally لضمان التنظيف بصرف النظر عن النتيجة. رتّب كتل catch المتعدّدة من الأكثر تحديدًا إلى الأكثر عمومية. في الدرس التالي ستستكشف التسلسل الهرمي الكامل للاستثناءات لتفهم تمامًا أي الأنواع تصطاد ومتى.