المسارات
/
Java
Java
/
المنهج
/
الاستثناءات
ال

الاستثناءات في Java

25 تمرينًا

نبذة عن الاستثناءات

تستخدم لغة البرمجة Java الاستثناءات للتعامل مع الأخطاء وغيرها من الأحداث الاستثنائية.

ما هو الاستثناء؟

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

في Java، جميع الاستثناءات أصناف فرعية للصنف Exception، وهو نفسه صنف فرعي للصنف Throwable.

وتميّز Java بين نوعين من الاستثناءات:

  1. الاستثناءات المُتحقَّق منها
  2. الاستثناءات غير المُتحقَّق منها

الاستثناءات المُتحقَّق منها

الاستثناءات المُتحقَّق منها هي حالات استثنائية ينبغي للتطبيق أن يتوقعها وأن يتعافى منها. ومن أمثلتها الاستثناء FileNotFoundException، ويحدث عندما تحاول طريقة قراءة ملف غير موجود.

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

جميع الاستثناءات المُتحقَّق منها هي أصناف فرعية للصنف Exception ولا ترث من RuntimeException.

الاستثناءات غير المُتحقَّق منها

الاستثناءات غير المُتحقَّق منها هي حالات استثنائية لا يستطيع التطبيق عادةً توقعها أو التعافي منها. ومن أمثلتها الاستثناء NullPointerException، ويحدث عندما تتوقع طريقة قيمةً ليست null لكنها تستقبل null.

لا يُتحقَّق من هذا النوع من الاستثناءات في وقت الترجمة: لا يُشترط على الطرق التي ترمي استثناءات غير مُتحقَّق منها أن تذكر ذلك في توقيع الطريقة، ولا يُشترط على الكود الذي يستدعي طريقة قد ترمي استثناءً غير مُتحقَّق منه أن يتعامل معه.

ترث جميع الاستثناءات غير المُتحقَّق منها من RuntimeException، وهو نفسه امتداد للصنف Exception.

رمي الاستثناءات

يمكن لطريقة في Java أن ترمي استثناءً باستخدام عبارة throw.

رمي استثناء مُتحقَّق منه

عند رمي استثناء مُتحقَّق منه من طريقة، يجب تحديد ذلك في توقيع الطريقة باستخدام الكلمة المفتاحية throws، كما يوضح المثال التالي. وهذا يُلزم الكود المستدعي بتوقع احتمال رمي استثناء والتعامل معه وفقًا لذلك.

public class InsufficientBalanceException extends Exception {

}

public class BankAccount {
  public void withdraw(double amount) throws InsufficientBalanceException {
    if (balance < amount) {
      throw new InsufficientBalanceException();
    }

    // rest of the method implementation
  }
}

رمي استثناء غير مُتحقَّق منه

عند رمي استثناء غير مُتحقَّق منه من طريقة، لا يجب تحديد ذلك في توقيع الطريقة، وإن كان ذلك مدعومًا.

public class BankAccount {
  public void withdraw(double amount) {
    if (amount < 0) {
      throw new IllegalArgumentException("Cannot withdraw a negative amount");
    }

    // rest of the method implementation
  }
}

التعامل مع الاستثناءات

يتم التعامل مع الاستثناءات في Java باستخدام الكلمات المفتاحية try وcatch وfinally.

  • ينبغي تغليف عبارات الكود التي قد ترمي استثناءً داخل كتلة try.
  • تلي كتلة try كتلة catch واحدة أو أكثر تلتقط الاستثناءات المرمية داخل كتلة try.
  • وقد تلي كتل catch كتلة finally تُنفَّذ دائمًا بعد كتلة try، سواء رُمي استثناء أم لم يُرمَ.

يوضح المثال التالي كيفية عمل هذه الكلمات المفتاحية:

public class ATM {
  public void withdraw(BankAccount bankAccount, double amount) {
    try {
      System.out.println("Withdrawing " + amount);
      bankAccount.withdraw(amount);
      System.out.println("Withdrawal succeeded");
    } catch (InsufficientBalanceException) {
      System.out.println("Withdrawal failed: insufficient balance");
    } catch (RuntimeException e) {
      System.out.println("Withdrawal failed: " + e.getMessage());
    } finally {
      System.out.println("Current balance: " + bankAccount.getBalance());
    }
  }
}

في هذا المثال، عندما لا يُرمى أي استثناء، تُطبع المخرجات التالية:

Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0

لكن إن كانت عبارة bankAccount.withdraw(amount) ترمي استثناء InsufficientBalanceException، فستُطبع المخرجات التالية:

Withdrawing 10.0
Withdrawal failed: insufficient balance
Current balance: 5.0

أو، في حال رمي استثناء غير مُتحقَّق منه بواسطة bankAccount.withdraw(amount)، تُطبع المخرجات التالية:

Withdrawing -10.0
Withdrawal failed: Cannot withdraw a negative amount
Current balance: 5.0

الأخطاء

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

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

ترث جميع الأخطاء في Java من الصنف Error.

متى لا تستخدم الاستثناءات

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

تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة

تعلّم الاستثناءات